|
|
|
from datetime import timedelta
|
|
|
|
from django.test import TestCase
|
|
|
|
from django.utils import timezone
|
|
|
|
from django.core.management import call_command
|
|
|
|
from django.core import mail
|
|
|
|
from io import StringIO
|
|
|
|
from constance import config as site_config
|
|
|
|
from constance.test import override_config
|
|
|
|
|
|
|
|
from .forms import SignupForm
|
|
|
|
from .models import VPNUser, User, random_gift_code, GiftCode, GiftCodeUser
|
|
|
|
from payments.models import Payment, Subscription
|
|
|
|
|
|
|
|
|
|
|
|
class UserTestMixin:
|
|
|
|
def assertRemaining(self, vpnuser, time):
|
|
|
|
""" Check that the vpnuser will expire in time (+/- 5 seconds) """
|
|
|
|
exp = vpnuser.expiration or timezone.now()
|
|
|
|
seconds = (exp - timezone.now() - time).total_seconds()
|
|
|
|
self.assertAlmostEqual(seconds, 0, delta=5)
|
|
|
|
|
|
|
|
|
|
|
|
class UserModelTest(TestCase, UserTestMixin):
|
|
|
|
def setUp(self):
|
|
|
|
User.objects.create_user('aaa')
|
|
|
|
|
|
|
|
def test_add_time(self):
|
|
|
|
u = User.objects.get(username='aaa')
|
|
|
|
vu = u.vpnuser
|
|
|
|
p = timedelta(days=1)
|
|
|
|
|
|
|
|
self.assertFalse(vu.is_paid)
|
|
|
|
|
|
|
|
vu.expiration = timezone.now()
|
|
|
|
vu.add_paid_time(p)
|
|
|
|
final = vu.expiration
|
|
|
|
|
|
|
|
self.assertRemaining(vu, p)
|
|
|
|
self.assertGreater(final, timezone.now())
|
|
|
|
self.assertTrue(vu.is_paid)
|
|
|
|
|
|
|
|
def test_add_time_past(self):
|
|
|
|
u = User.objects.get(username='aaa')
|
|
|
|
vu = u.vpnuser
|
|
|
|
p = timedelta(days=1)
|
|
|
|
|
|
|
|
self.assertFalse(vu.is_paid)
|
|
|
|
|
|
|
|
vu.expiration = timezone.now() - timedelta(days=135)
|
|
|
|
vu.add_paid_time(p)
|
|
|
|
final = vu.expiration
|
|
|
|
|
|
|
|
self.assertRemaining(vu, p)
|
|
|
|
self.assertGreater(final, timezone.now())
|
|
|
|
self.assertTrue(vu.is_paid)
|
|
|
|
|
|
|
|
def test_add_time_initial(self):
|
|
|
|
u = User.objects.get(username='aaa')
|
|
|
|
vu = u.vpnuser
|
|
|
|
p = timedelta(days=1)
|
|
|
|
|
|
|
|
self.assertFalse(vu.is_paid)
|
|
|
|
|
|
|
|
vu.add_paid_time(p)
|
|
|
|
self.assertTrue(vu.is_paid)
|
|
|
|
|
|
|
|
def test_paid_between_subscr_payments(self):
|
|
|
|
u = User.objects.get(username='aaa')
|
|
|
|
vu = u.vpnuser
|
|
|
|
s = Subscription(user=u, backend_id='paypal', status='new')
|
|
|
|
s.save()
|
|
|
|
|
|
|
|
self.assertFalse(vu.is_paid)
|
|
|
|
|
|
|
|
s.status = 'active'
|
|
|
|
s.save()
|
|
|
|
|
|
|
|
self.assertTrue(vu.is_paid)
|
|
|
|
|
|
|
|
def test_grant_trial(self):
|
|
|
|
p = timedelta(days=1)
|
|
|
|
u = User.objects.get(username='aaa')
|
|
|
|
vu = u.vpnuser
|
|
|
|
|
|
|
|
with override_config(TRIAL_PERIOD_HOURS=24, TRIAL_PERIOD_MAX=2):
|
|
|
|
self.assertEqual(vu.remaining_trial_periods, 2)
|
|
|
|
self.assertTrue(vu.can_have_trial)
|
|
|
|
vu.give_trial_period()
|
|
|
|
self.assertRemaining(vu, p)
|
|
|
|
|
|
|
|
self.assertEqual(vu.remaining_trial_periods, 1)
|
|
|
|
self.assertTrue(vu.can_have_trial)
|
|
|
|
vu.give_trial_period()
|
|
|
|
self.assertRemaining(vu, p * 2)
|
|
|
|
|
|
|
|
self.assertEqual(vu.remaining_trial_periods, 0)
|
|
|
|
self.assertFalse(vu.can_have_trial)
|
|
|
|
|
|
|
|
def test_trial_refused(self):
|
|
|
|
p = timedelta(days=1)
|
|
|
|
u = User.objects.get(username='aaa')
|
|
|
|
payment = Payment.objects.create(user=u, status='confirmed', amount=300,
|
|
|
|
time=timedelta(days=30))
|
|
|
|
payment.save()
|
|
|
|
|
|
|
|
vu = u.vpnuser
|
|
|
|
|
|
|
|
with override_config(TRIAL_PERIOD_HOURS=24, TRIAL_PERIOD_MAX=2):
|
|
|
|
self.assertEqual(vu.remaining_trial_periods, 2)
|
|
|
|
self.assertFalse(vu.can_have_trial)
|
|
|
|
|
|
|
|
|
|
|
|
class UserModelReferrerTest(TestCase, UserTestMixin):
|
|
|
|
def setUp(self):
|
|
|
|
self.referrer = User.objects.create_user('ref')
|
|
|
|
|
|
|
|
self.without_ref = User.objects.create_user('aaaa')
|
|
|
|
|
|
|
|
self.with_ref = User.objects.create_user('bbbb')
|
|
|
|
self.with_ref.vpnuser.referrer = self.referrer
|
|
|
|
|
|
|
|
self.payment = Payment.objects.create(
|
|
|
|
user=self.with_ref, status='confirmed', amount=300, time=timedelta(days=30))
|
|
|
|
|
|
|
|
def test_no_ref(self):
|
|
|
|
self.without_ref.vpnuser.on_payment_confirmed(self.payment)
|
|
|
|
|
|
|
|
def test_ref(self):
|
|
|
|
self.with_ref.vpnuser.on_payment_confirmed(self.payment)
|
|
|
|
self.assertTrue(self.with_ref.vpnuser.referrer_used)
|
|
|
|
self.assertEqual(self.with_ref.vpnuser.referrer, self.referrer)
|
|
|
|
self.assertRemaining(self.referrer.vpnuser, timedelta(days=14))
|
|
|
|
|
|
|
|
|
|
|
|
class GCModelTest(TestCase):
|
|
|
|
def test_generator(self):
|
|
|
|
c = random_gift_code()
|
|
|
|
self.assertEqual(len(c), 10)
|
|
|
|
self.assertNotEqual(c, random_gift_code())
|
|
|
|
|
|
|
|
|
|
|
|
class SignupViewTest(TestCase):
|
|
|
|
def test_form(self):
|
|
|
|
response = self.client.get('/account/signup')
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
self.assertIsInstance(response.context['form'], SignupForm)
|
|
|
|
|
|
|
|
def test_post(self):
|
|
|
|
response = self.client.post('/account/signup', {
|
|
|
|
'username': 'test_un', 'password': 'test_pw', 'password2': 'test_pw'})
|
|
|
|
self.assertRedirects(response, '/account/')
|
|
|
|
|
|
|
|
user = User.objects.get(username='test_un')
|
|
|
|
self.assertTrue(user.check_password('test_pw'))
|
|
|
|
|
|
|
|
def test_post_error(self):
|
|
|
|
response = self.client.post('/account/signup', {
|
|
|
|
'username': 'test_un', 'password': 'test_pw', 'password2': 'qsdf'})
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
self.assertIsInstance(response.context['form'], SignupForm)
|
|
|
|
self.assertFormError(response, 'form', 'password',
|
|
|
|
'Passwords are not the same')
|
|
|
|
|
|
|
|
def test_post_referrer(self):
|
|
|
|
ref = User.objects.create_user('referrer')
|
|
|
|
|
|
|
|
response = self.client.post('/account/signup?ref=%d' % ref.id, {
|
|
|
|
'username': 'test_un', 'password': 'test_pw', 'password2': 'test_pw'})
|
|
|
|
self.assertRedirects(response, '/account/')
|
|
|
|
|
|
|
|
user = User.objects.get(username='test_un')
|
|
|
|
self.assertTrue(user.check_password('test_pw'))
|
|
|
|
self.assertEqual(user.vpnuser.referrer, ref)
|
|
|
|
|
|
|
|
|
|
|
|
class AccountViewsTest(TestCase, UserTestMixin):
|
|
|
|
def setUp(self):
|
|
|
|
User.objects.create_user('test', None, 'test_pw')
|
|
|
|
self.client.login(username='test', password='test_pw')
|
|
|
|
|
|
|
|
def test_account(self):
|
|
|
|
response = self.client.get('/account/')
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
|
|
|
def test_settings_form(self):
|
|
|
|
response = self.client.get('/account/settings')
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
|
|
|
def print_message(self, response):
|
|
|
|
from django.contrib.messages import get_messages
|
|
|
|
messages = list(get_messages(response.wsgi_request))
|
|
|
|
for m in messages:
|
|
|
|
print(f"[message: {m.message!r} level={m.level} tags={m.tags!r}]")
|
|
|
|
|
|
|
|
def test_settings_post_email(self):
|
|
|
|
response = self.client.post('/account/settings', {
|
|
|
|
'action': 'email',
|
|
|
|
'current_password': 'test_pw',
|
|
|
|
'email': 'new_email@example.com'})
|
|
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertEqual(user.email, 'new_email@example.com')
|
|
|
|
|
|
|
|
def test_settings_post_email_fail(self):
|
|
|
|
response = self.client.post('/account/settings', {
|
|
|
|
'action': 'email',
|
|
|
|
'current_password': 'not_test_pw',
|
|
|
|
'email': 'new_email@example.com'})
|
|
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertNotEqual(user.email, 'new_email@example.com')
|
|
|
|
|
|
|
|
def test_settings_post_pw(self):
|
|
|
|
response = self.client.post('/account/settings', {
|
|
|
|
'action': 'password',
|
|
|
|
'current_password': 'test_pw',
|
|
|
|
'password': 'new_test_pw', 'password2': 'new_test_pw'})
|
|
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertTrue(user.check_password('new_test_pw'))
|
|
|
|
|
|
|
|
def test_settings_post_pw_fail(self):
|
|
|
|
response = self.client.post('/account/settings', {
|
|
|
|
'action': 'password',
|
|
|
|
'current_password': 'oops',
|
|
|
|
'password': 'new_test_pw',
|
|
|
|
'password2': 'new_test_pw'})
|
|
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
|
|
|
|
response = self.client.post('/account/settings', {
|
|
|
|
'action': 'password',
|
|
|
|
'current_password': 'test_pw',
|
|
|
|
'password': 'new_test_pw2',
|
|
|
|
'password2': 'new_test_pw_qsdfg'})
|
|
|
|
self.assertEqual(response.status_code, 302)
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertFalse(user.check_password('new_test_pw'))
|
|
|
|
self.assertFalse(user.check_password('new_test_pw2'))
|
|
|
|
self.assertTrue(user.check_password('test_pw'))
|
|
|
|
|
|
|
|
def test_giftcode_use_single(self):
|
|
|
|
gc = GiftCode.objects.create(time=timedelta(days=42), single_use=True)
|
|
|
|
|
|
|
|
response = self.client.post('/account/gift_code', {'code': gc.code})
|
|
|
|
self.assertRedirects(response, '/account/')
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertRemaining(user.vpnuser, timedelta(days=42))
|
|
|
|
|
|
|
|
response = self.client.post('/account/gift_code', {'code': gc.code})
|
|
|
|
self.assertRedirects(response, '/account/')
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertRemaining(user.vpnuser, timedelta(days=42)) # same expiration
|
|
|
|
|
|
|
|
def test_giftcode_use_free_only(self):
|
|
|
|
gc = GiftCode.objects.create(time=timedelta(days=42), free_only=True)
|
|
|
|
|
|
|
|
response = self.client.post('/account/gift_code', {'code': gc.code})
|
|
|
|
self.assertRedirects(response, '/account/')
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertRemaining(user.vpnuser, timedelta(days=42))
|
|
|
|
|
|
|
|
def test_giftcode_use_free_only_fail(self):
|
|
|
|
gc = GiftCode.objects.create(time=timedelta(days=42), free_only=True)
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
user.vpnuser.add_paid_time(timedelta(days=1))
|
|
|
|
user.vpnuser.save()
|
|
|
|
|
|
|
|
response = self.client.post('/account/gift_code', {'code': gc.code})
|
|
|
|
self.assertRedirects(response, '/account/')
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
self.assertRemaining(user.vpnuser, timedelta(days=1))
|
|
|
|
|
|
|
|
def test_giftcode_create_gcu(self):
|
|
|
|
gc = GiftCode.objects.create(time=timedelta(days=42))
|
|
|
|
|
|
|
|
response = self.client.post('/account/gift_code', {'code': gc.code})
|
|
|
|
self.assertRedirects(response, '/account/')
|
|
|
|
|
|
|
|
user = User.objects.get(username='test')
|
|
|
|
gcu = GiftCodeUser.objects.get(user=user, code=gc)
|
|
|
|
|
|
|
|
self.assertRemaining(user.vpnuser, timedelta(days=42))
|
|
|
|
self.assertIn(gcu, user.giftcodeuser_set.all())
|
|
|
|
|
|
|
|
|
|
|
|
class CACrtViewTest(TestCase):
|
|
|
|
def test_ca_crt(self):
|
|
|
|
with self.settings(OPENVPN_CA='test ca'):
|
|
|
|
response = self.client.get('/ca.crt')
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
self.assertEqual(response['Content-Type'], 'application/x-x509-ca-cert')
|
|
|
|
self.assertEqual(response.content, b'test ca')
|
|
|
|
|
|
|
|
|
|
|
|
def email_text(body):
|
|
|
|
return body.replace('\n', ' ') \
|
|
|
|
.replace('\xa0', ' ') # nbsp
|
|
|
|
|
|
|
|
|
|
|
|
class ExpireNotifyTest(TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def test_notify_first(self):
|
|
|
|
out = StringIO()
|
|
|
|
u = User.objects.create_user('test_username', 'test@example.com', 'testpw')
|
|
|
|
u.vpnuser.add_paid_time(timedelta(days=2))
|
|
|
|
u.vpnuser.save()
|
|
|
|
|
|
|
|
call_command('expire_notify', stdout=out)
|
|
|
|
self.assertEqual(len(mail.outbox), 1)
|
|
|
|
self.assertEqual(mail.outbox[0].to, ['test@example.com'])
|
|
|
|
self.assertIn('expire in 1 day', email_text(mail.outbox[0].body))
|
|
|
|
|
|
|
|
u = User.objects.get(username='test_username')
|
|
|
|
self.assertAlmostEqual(u.vpnuser.last_expiry_notice, timezone.now(),
|
|
|
|
delta=timedelta(minutes=1))
|
|
|
|
|
|
|
|
def test_notify_second(self):
|
|
|
|
out = StringIO()
|
|
|
|
u = User.objects.create_user('test_username', 'test@example.com', 'testpw')
|
|
|
|
u.vpnuser.last_expiry_notice = timezone.now() - timedelta(days=2)
|
|
|
|
u.vpnuser.add_paid_time(timedelta(days=1))
|
|
|
|
u.vpnuser.save()
|
|
|
|
|
|
|
|
call_command('expire_notify', stdout=out)
|
|
|
|
self.assertEqual(len(mail.outbox), 1)
|
|
|
|
self.assertEqual(mail.outbox[0].to, ['test@example.com'])
|
|
|
|
self.assertIn('expire in 23 hours, 59 minutes', email_text(mail.outbox[0].body))
|
|
|
|
|
|
|
|
u = User.objects.get(username='test_username')
|
|
|
|
self.assertAlmostEqual(u.vpnuser.last_expiry_notice, timezone.now(),
|
|
|
|
delta=timedelta(minutes=1))
|
|
|
|
|
|
|
|
def test_notify_subscription(self):
|
|
|
|
out = StringIO()
|
|
|
|
u = User.objects.create_user('test_username', 'test@example.com', 'testpw')
|
|
|
|
u.vpnuser.add_paid_time(timedelta(days=2))
|
|
|
|
u.vpnuser.save()
|
|
|
|
|
|
|
|
s = Subscription(user=u, backend_id='paypal', status='active')
|
|
|
|
s.save()
|
|
|
|
|
|
|
|
call_command('expire_notify', stdout=out)
|
|
|
|
self.assertEqual(len(mail.outbox), 0)
|
|
|
|
|
|
|
|
u = User.objects.get(username='test_username')
|
|
|
|
# FIXME:
|
|
|
|
# self.assertNotAlmostEqual(u.vpnuser.last_expiry_notice, timezone.now(),
|
|
|
|
# delta=timedelta(minutes=1))
|
|
|
|
|
|
|
|
def test_notify_subscription_new(self):
|
|
|
|
out = StringIO()
|
|
|
|
u = User.objects.create_user('test_username', 'test@example.com', 'testpw')
|
|
|
|
u.vpnuser.add_paid_time(timedelta(days=2))
|
|
|
|
u.vpnuser.last_expiry_notice = timezone.now() - timedelta(days=5)
|
|
|
|
u.vpnuser.save()
|
|
|
|
|
|
|
|
s = Subscription(user=u, backend_id='paypal', status='new')
|
|
|
|
s.save()
|
|
|
|
|
|
|
|
call_command('expire_notify', stdout=out)
|
|
|
|
self.assertEqual(len(mail.outbox), 1)
|
|
|
|
|
|
|
|
u = User.objects.get(username='test_username')
|
|
|
|
# FIXME:
|
|
|
|
# self.assertNotAlmostEqual(u.vpnuser.last_expiry_notice, timezone.now(),
|
|
|
|
# delta=timedelta(minutes=1))
|
|
|
|
|
|
|
|
|