forked from GithubBackups/healthchecks
Project model. cc: #183
This commit is contained in:
parent
b4635c69e7
commit
1c69cf7f89
@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Database schema: add Ping.kind field
|
- Database schema: add Ping.kind field
|
||||||
- Database schema: remove Ping.start and Ping.fail fields
|
- Database schema: remove Ping.start and Ping.fail fields
|
||||||
- Add "Email Settings..." dialog and "Subject Must Contain" setting
|
- Add "Email Settings..." dialog and "Subject Must Contain" setting
|
||||||
|
- Database schema: add the Project model
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 1.4.0 - 2018-12-25
|
## 1.4.0 - 2018-12-25
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from django.db.models import Count
|
|||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from hc.accounts.models import Profile
|
from hc.accounts.models import Profile, Project
|
||||||
|
|
||||||
|
|
||||||
class Fieldset:
|
class Fieldset:
|
||||||
@ -85,6 +85,15 @@ class ProfileAdmin(admin.ModelAdmin):
|
|||||||
return obj.user.email
|
return obj.user.email
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Project)
|
||||||
|
class ProjectAdmin(admin.ModelAdmin):
|
||||||
|
list_select_related = ("owner", )
|
||||||
|
list_display = ("id", "name", "email")
|
||||||
|
|
||||||
|
def email(self, obj):
|
||||||
|
return obj.owner.email
|
||||||
|
|
||||||
|
|
||||||
class HcUserAdmin(UserAdmin):
|
class HcUserAdmin(UserAdmin):
|
||||||
actions = ["send_report"]
|
actions = ["send_report"]
|
||||||
list_display = ('id', 'email', 'date_joined', 'last_login', 'engagement',
|
list_display = ('id', 'email', 'date_joined', 'last_login', 'engagement',
|
||||||
|
|||||||
@ -16,4 +16,8 @@ class TeamAccessMiddleware(object):
|
|||||||
request.profile = Profile.objects.for_user(request.user)
|
request.profile = Profile.objects.for_user(request.user)
|
||||||
request.team = request.profile.team()
|
request.team = request.profile.team()
|
||||||
|
|
||||||
|
request.project = request.profile.current_project
|
||||||
|
if request.project is None:
|
||||||
|
request.project = request.team.user.project_set.first()
|
||||||
|
|
||||||
return self.get_response(request)
|
return self.get_response(request)
|
||||||
|
|||||||
38
hc/accounts/migrations/0017_auto_20190112_1426.py
Normal file
38
hc/accounts/migrations/0017_auto_20190112_1426.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-01-12 14:26
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('accounts', '0016_remove_profile_bill_to'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Project',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('code', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||||
|
('name', models.CharField(blank=True, max_length=200)),
|
||||||
|
('api_key', models.CharField(blank=True, max_length=128)),
|
||||||
|
('api_key_readonly', models.CharField(blank=True, max_length=128)),
|
||||||
|
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='member',
|
||||||
|
name='project',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.Project'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='profile',
|
||||||
|
name='current_project',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.Project'),
|
||||||
|
),
|
||||||
|
]
|
||||||
37
hc/accounts/migrations/0018_auto_20190112_1426.py
Normal file
37
hc/accounts/migrations/0018_auto_20190112_1426.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-01-11 14:49
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def create_projects(apps, schema_editor):
|
||||||
|
Profile = apps.get_model("accounts", "Profile")
|
||||||
|
Project = apps.get_model("accounts", "Project")
|
||||||
|
Member = apps.get_model("accounts", "Member")
|
||||||
|
for profile in Profile.objects.all():
|
||||||
|
project = Project()
|
||||||
|
project.name = profile.team_name
|
||||||
|
project.owner_id = profile.user_id
|
||||||
|
project.api_key = profile.api_key
|
||||||
|
project.api_key_readonly = profile.api_key_readonly
|
||||||
|
project.save()
|
||||||
|
|
||||||
|
profile.current_project = project
|
||||||
|
profile.save()
|
||||||
|
|
||||||
|
Member.objects.filter(team=profile).update(project=project)
|
||||||
|
|
||||||
|
for profile in Profile.objects.all():
|
||||||
|
if profile.current_team_id:
|
||||||
|
profile.current_project = profile.current_team.current_project
|
||||||
|
profile.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0017_auto_20190112_1426'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(create_projects, migrations.RunPython.noop),
|
||||||
|
]
|
||||||
@ -1,6 +1,7 @@
|
|||||||
from base64 import urlsafe_b64encode
|
from base64 import urlsafe_b64encode
|
||||||
import os
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.hashers import check_password, make_password
|
from django.contrib.auth.hashers import check_password, make_password
|
||||||
@ -54,6 +55,7 @@ class Profile(models.Model):
|
|||||||
api_key = models.CharField(max_length=128, blank=True)
|
api_key = models.CharField(max_length=128, blank=True)
|
||||||
api_key_readonly = models.CharField(max_length=128, blank=True)
|
api_key_readonly = models.CharField(max_length=128, blank=True)
|
||||||
current_team = models.ForeignKey("self", models.SET_NULL, null=True)
|
current_team = models.ForeignKey("self", models.SET_NULL, null=True)
|
||||||
|
current_project = models.ForeignKey("Project", models.SET_NULL, null=True)
|
||||||
last_sms_date = models.DateTimeField(null=True, blank=True)
|
last_sms_date = models.DateTimeField(null=True, blank=True)
|
||||||
sms_limit = models.IntegerField(default=0)
|
sms_limit = models.IntegerField(default=0)
|
||||||
sms_sent = models.IntegerField(default=0)
|
sms_sent = models.IntegerField(default=0)
|
||||||
@ -185,8 +187,9 @@ class Profile(models.Model):
|
|||||||
return self.member_set.count() < self.team_limit
|
return self.member_set.count() < self.team_limit
|
||||||
|
|
||||||
def invite(self, user):
|
def invite(self, user):
|
||||||
member = Member(team=self, user=user)
|
for project in self.user.project_set.all():
|
||||||
member.save()
|
member = Member(team=self, user=user, project=project)
|
||||||
|
member.save()
|
||||||
|
|
||||||
# Switch the invited user over to the new team so they
|
# Switch the invited user over to the new team so they
|
||||||
# notice the new team on next visit:
|
# notice the new team on next visit:
|
||||||
@ -231,6 +234,15 @@ class Profile(models.Model):
|
|||||||
q.update(next_nag_date=timezone.now() + models.F("nag_period"))
|
q.update(next_nag_date=timezone.now() + models.F("nag_period"))
|
||||||
|
|
||||||
|
|
||||||
|
class Project(models.Model):
|
||||||
|
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||||
|
name = models.CharField(max_length=200, blank=True)
|
||||||
|
owner = models.ForeignKey(User, models.CASCADE)
|
||||||
|
api_key = models.CharField(max_length=128, blank=True)
|
||||||
|
api_key_readonly = models.CharField(max_length=128, blank=True)
|
||||||
|
|
||||||
|
|
||||||
class Member(models.Model):
|
class Member(models.Model):
|
||||||
team = models.ForeignKey(Profile, models.CASCADE)
|
team = models.ForeignKey(Profile, models.CASCADE)
|
||||||
user = models.ForeignKey(User, models.CASCADE, related_name="memberships")
|
user = models.ForeignKey(User, models.CASCADE, related_name="memberships")
|
||||||
|
project = models.ForeignKey(Project, models.CASCADE, null=True)
|
||||||
|
|||||||
@ -27,6 +27,7 @@ class CloseAccountTestCase(BaseTestCase):
|
|||||||
# Bob's current team should now be None
|
# Bob's current team should now be None
|
||||||
self.bobs_profile.refresh_from_db()
|
self.bobs_profile.refresh_from_db()
|
||||||
self.assertIsNone(self.bobs_profile.current_team)
|
self.assertIsNone(self.bobs_profile.current_team)
|
||||||
|
self.assertIsNone(self.bobs_profile.current_project)
|
||||||
|
|
||||||
# Check should be gone
|
# Check should be gone
|
||||||
self.assertFalse(Check.objects.exists())
|
self.assertFalse(Check.objects.exists())
|
||||||
|
|||||||
@ -39,6 +39,9 @@ class ProfileTestCase(BaseTestCase):
|
|||||||
self.assertTrue(len(api_key) > 10)
|
self.assertTrue(len(api_key) > 10)
|
||||||
self.assertFalse("b'" in api_key)
|
self.assertFalse("b'" in api_key)
|
||||||
|
|
||||||
|
self.project.refresh_from_db()
|
||||||
|
self.assertEqual(self.project.api_key, api_key)
|
||||||
|
|
||||||
def test_it_revokes_api_key(self):
|
def test_it_revokes_api_key(self):
|
||||||
self.profile.api_key_readonly = "R" * 32
|
self.profile.api_key_readonly = "R" * 32
|
||||||
self.profile.save()
|
self.profile.save()
|
||||||
@ -53,6 +56,9 @@ class ProfileTestCase(BaseTestCase):
|
|||||||
self.assertEqual(self.profile.api_key, "")
|
self.assertEqual(self.profile.api_key, "")
|
||||||
self.assertEqual(self.profile.api_key_readonly, "")
|
self.assertEqual(self.profile.api_key_readonly, "")
|
||||||
|
|
||||||
|
self.project.refresh_from_db()
|
||||||
|
self.assertEqual(self.project.api_key, "")
|
||||||
|
|
||||||
def test_it_sends_report(self):
|
def test_it_sends_report(self):
|
||||||
check = Check(name="Test Check", user=self.alice)
|
check = Check(name="Test Check", user=self.alice)
|
||||||
check.last_ping = now()
|
check.last_ping = now()
|
||||||
@ -126,12 +132,16 @@ class ProfileTestCase(BaseTestCase):
|
|||||||
r = self.client.post("/accounts/profile/", form)
|
r = self.client.post("/accounts/profile/", form)
|
||||||
self.assertEqual(r.status_code, 200)
|
self.assertEqual(r.status_code, 200)
|
||||||
|
|
||||||
member_emails = set()
|
members = self.profile.member_set.all()
|
||||||
for member in self.profile.member_set.all():
|
self.assertEqual(members.count(), 2)
|
||||||
member_emails.add(member.user.email)
|
|
||||||
|
|
||||||
self.assertEqual(len(member_emails), 2)
|
frank_found = False
|
||||||
self.assertTrue("frank@example.org" in member_emails)
|
for member in members.all():
|
||||||
|
self.assertEqual(member.project, self.project)
|
||||||
|
if member.user.email == "frank@example.org":
|
||||||
|
frank_found = True
|
||||||
|
|
||||||
|
self.assertTrue(frank_found)
|
||||||
|
|
||||||
# And an email should have been sent
|
# And an email should have been sent
|
||||||
subj = ('You have been invited to join'
|
subj = ('You have been invited to join'
|
||||||
@ -159,6 +169,7 @@ class ProfileTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.bobs_profile.refresh_from_db()
|
self.bobs_profile.refresh_from_db()
|
||||||
self.assertEqual(self.bobs_profile.current_team, None)
|
self.assertEqual(self.bobs_profile.current_team, None)
|
||||||
|
self.assertEqual(self.bobs_profile.current_project, None)
|
||||||
|
|
||||||
def test_it_sets_team_name(self):
|
def test_it_sets_team_name(self):
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
@ -170,6 +181,9 @@ class ProfileTestCase(BaseTestCase):
|
|||||||
self.profile.refresh_from_db()
|
self.profile.refresh_from_db()
|
||||||
self.assertEqual(self.profile.team_name, "Alpha Team")
|
self.assertEqual(self.profile.team_name, "Alpha Team")
|
||||||
|
|
||||||
|
self.project.refresh_from_db()
|
||||||
|
self.assertEqual(self.project.name, "Alpha Team")
|
||||||
|
|
||||||
def test_it_switches_to_own_team(self):
|
def test_it_switches_to_own_team(self):
|
||||||
self.client.login(username="bob@example.org", password="password")
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
|
||||||
@ -179,6 +193,7 @@ class ProfileTestCase(BaseTestCase):
|
|||||||
# to user's default team.
|
# to user's default team.
|
||||||
self.bobs_profile.refresh_from_db()
|
self.bobs_profile.refresh_from_db()
|
||||||
self.assertEqual(self.bobs_profile.current_team, self.bobs_profile)
|
self.assertEqual(self.bobs_profile.current_team, self.bobs_profile)
|
||||||
|
self.assertEqual(self.bobs_profile.current_project, None)
|
||||||
|
|
||||||
def test_it_sends_change_email_link(self):
|
def test_it_sends_change_email_link(self):
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
|||||||
@ -2,7 +2,8 @@ from django.contrib.auth.models import User
|
|||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.utils import override_settings
|
from django.test.utils import override_settings
|
||||||
from hc.api.models import Check
|
from hc.accounts.models import Project
|
||||||
|
from hc.api.models import Channel, Check
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
@ -15,16 +16,25 @@ class SignupTestCase(TestCase):
|
|||||||
self.assertContains(r, "Account created")
|
self.assertContains(r, "Account created")
|
||||||
|
|
||||||
# An user should have been created
|
# An user should have been created
|
||||||
self.assertEqual(User.objects.count(), 1)
|
user = User.objects.get()
|
||||||
|
|
||||||
# And email sent
|
# And email sent
|
||||||
self.assertEqual(len(mail.outbox), 1)
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
subject = "Log in to %s" % settings.SITE_NAME
|
subject = "Log in to %s" % settings.SITE_NAME
|
||||||
self.assertEqual(mail.outbox[0].subject, subject)
|
self.assertEqual(mail.outbox[0].subject, subject)
|
||||||
|
|
||||||
|
# A project should have been created
|
||||||
|
project = Project.objects.get()
|
||||||
|
self.assertEqual(project.owner, user)
|
||||||
|
|
||||||
# And check should be associated with the new user
|
# And check should be associated with the new user
|
||||||
check = Check.objects.get()
|
check = Check.objects.get()
|
||||||
self.assertEqual(check.name, "My First Check")
|
self.assertEqual(check.name, "My First Check")
|
||||||
|
self.assertEqual(check.project, project)
|
||||||
|
|
||||||
|
# A channel should have been created
|
||||||
|
channel = Channel.objects.get()
|
||||||
|
self.assertEqual(channel.project, project)
|
||||||
|
|
||||||
@override_settings(REGISTRATION_OPEN=False)
|
@override_settings(REGISTRATION_OPEN=False)
|
||||||
def test_it_obeys_registration_open(self):
|
def test_it_obeys_registration_open(self):
|
||||||
|
|||||||
@ -5,6 +5,9 @@ from hc.api.models import Check
|
|||||||
class SwitchTeamTestCase(BaseTestCase):
|
class SwitchTeamTestCase(BaseTestCase):
|
||||||
|
|
||||||
def test_it_switches(self):
|
def test_it_switches(self):
|
||||||
|
self.bobs_profile.current_project = None
|
||||||
|
self.bobs_profile.save()
|
||||||
|
|
||||||
c = Check(user=self.alice, name="This belongs to Alice")
|
c = Check(user=self.alice, name="This belongs to Alice")
|
||||||
c.save()
|
c.save()
|
||||||
|
|
||||||
@ -15,6 +18,9 @@ class SwitchTeamTestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.assertContains(r, "This belongs to Alice")
|
self.assertContains(r, "This belongs to Alice")
|
||||||
|
|
||||||
|
self.bobs_profile.refresh_from_db()
|
||||||
|
self.assertEqual(self.bobs_profile.current_project, self.project)
|
||||||
|
|
||||||
def test_it_checks_team_membership(self):
|
def test_it_checks_team_membership(self):
|
||||||
self.client.login(username="charlie@example.org", password="password")
|
self.client.login(username="charlie@example.org", password="password")
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ from hc.accounts.forms import (ChangeEmailForm, EmailPasswordForm,
|
|||||||
ReportSettingsForm, SetPasswordForm,
|
ReportSettingsForm, SetPasswordForm,
|
||||||
TeamNameForm, AvailableEmailForm,
|
TeamNameForm, AvailableEmailForm,
|
||||||
ExistingEmailForm)
|
ExistingEmailForm)
|
||||||
from hc.accounts.models import Profile, Member
|
from hc.accounts.models import Profile, Project, Member
|
||||||
from hc.api.models import Channel, Check
|
from hc.api.models import Channel, Check
|
||||||
from hc.lib.badges import get_badge_url
|
from hc.lib.badges import get_badge_url
|
||||||
from hc.payments.models import Subscription
|
from hc.payments.models import Subscription
|
||||||
@ -49,14 +49,19 @@ def _make_user(email):
|
|||||||
user.set_unusable_password()
|
user.set_unusable_password()
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
# Ensure a profile gets created
|
project = Project(owner=user)
|
||||||
Profile.objects.for_user(user)
|
project.save()
|
||||||
|
|
||||||
check = Check(user=user)
|
# Ensure a profile gets created
|
||||||
|
profile = Profile.objects.for_user(user)
|
||||||
|
profile.current_project = project
|
||||||
|
profile.save()
|
||||||
|
|
||||||
|
check = Check(user=user, project=project)
|
||||||
check.name = "My First Check"
|
check.name = "My First Check"
|
||||||
check.save()
|
check.save()
|
||||||
|
|
||||||
channel = Channel(user=user)
|
channel = Channel(user=user, project=project)
|
||||||
channel.kind = "email"
|
channel.kind = "email"
|
||||||
channel.value = email
|
channel.value = email
|
||||||
channel.email_verified = True
|
channel.email_verified = True
|
||||||
@ -72,7 +77,10 @@ def _ensure_own_team(request):
|
|||||||
|
|
||||||
if request.team != request.profile:
|
if request.team != request.profile:
|
||||||
request.team = request.profile
|
request.team = request.profile
|
||||||
|
request.project = request.user.project_set.first()
|
||||||
|
|
||||||
request.profile.current_team = request.profile
|
request.profile.current_team = request.profile
|
||||||
|
request.profile.current_project = request.project
|
||||||
request.profile.save()
|
request.profile.save()
|
||||||
|
|
||||||
|
|
||||||
@ -200,6 +208,12 @@ def profile(request):
|
|||||||
return redirect("hc-link-sent")
|
return redirect("hc-link-sent")
|
||||||
elif "create_api_keys" in request.POST:
|
elif "create_api_keys" in request.POST:
|
||||||
profile.set_api_keys()
|
profile.set_api_keys()
|
||||||
|
|
||||||
|
for project in request.user.project_set.all():
|
||||||
|
project.api_key = profile.api_key
|
||||||
|
project.api_key_readonly = profile.api_key_readonly
|
||||||
|
project.save()
|
||||||
|
|
||||||
ctx["show_api_keys"] = True
|
ctx["show_api_keys"] = True
|
||||||
ctx["api_keys_created"] = True
|
ctx["api_keys_created"] = True
|
||||||
ctx["api_status"] = "success"
|
ctx["api_status"] = "success"
|
||||||
@ -208,6 +222,12 @@ def profile(request):
|
|||||||
profile.api_key = ""
|
profile.api_key = ""
|
||||||
profile.api_key_readonly = ""
|
profile.api_key_readonly = ""
|
||||||
profile.save()
|
profile.save()
|
||||||
|
|
||||||
|
for project in request.user.project_set.all():
|
||||||
|
project.api_key = ""
|
||||||
|
project.api_key_readonly = ""
|
||||||
|
project.save()
|
||||||
|
|
||||||
ctx["api_keys_revoked"] = True
|
ctx["api_keys_revoked"] = True
|
||||||
ctx["api_status"] = "info"
|
ctx["api_status"] = "info"
|
||||||
elif "show_api_keys" in request.POST:
|
elif "show_api_keys" in request.POST:
|
||||||
@ -236,6 +256,7 @@ def profile(request):
|
|||||||
email = form.cleaned_data["email"]
|
email = form.cleaned_data["email"]
|
||||||
farewell_user = User.objects.get(email=email)
|
farewell_user = User.objects.get(email=email)
|
||||||
farewell_user.profile.current_team = None
|
farewell_user.profile.current_team = None
|
||||||
|
farewell_user.profile.current_project = None
|
||||||
farewell_user.profile.save()
|
farewell_user.profile.save()
|
||||||
|
|
||||||
Member.objects.filter(team=profile,
|
Member.objects.filter(team=profile,
|
||||||
@ -248,6 +269,11 @@ def profile(request):
|
|||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
profile.team_name = form.cleaned_data["team_name"]
|
profile.team_name = form.cleaned_data["team_name"]
|
||||||
profile.save()
|
profile.save()
|
||||||
|
|
||||||
|
for project in request.user.project_set.all():
|
||||||
|
project.name = form.cleaned_data["team_name"]
|
||||||
|
project.save()
|
||||||
|
|
||||||
ctx["team_name_updated"] = True
|
ctx["team_name_updated"] = True
|
||||||
ctx["team_status"] = "success"
|
ctx["team_status"] = "success"
|
||||||
|
|
||||||
@ -427,6 +453,7 @@ def switch_team(request, target_username):
|
|||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
request.profile.current_team = target_team
|
request.profile.current_team = target_team
|
||||||
|
request.profile.current_project = target_team.user.project_set.first()
|
||||||
request.profile.save()
|
request.profile.save()
|
||||||
|
|
||||||
return redirect("hc-checks")
|
return redirect("hc-checks")
|
||||||
|
|||||||
@ -24,6 +24,7 @@ def authorize(f):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
request.user = User.objects.get(profile__api_key=api_key)
|
request.user = User.objects.get(profile__api_key=api_key)
|
||||||
|
request.project = request.user.project_set.first()
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return error("wrong api key", 401)
|
return error("wrong api key", 401)
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ def authorize_read(f):
|
|||||||
read_key_match = Q(profile__api_key_readonly=api_key)
|
read_key_match = Q(profile__api_key_readonly=api_key)
|
||||||
try:
|
try:
|
||||||
request.user = User.objects.get(write_key_match | read_key_match)
|
request.user = User.objects.get(write_key_match | read_key_match)
|
||||||
|
request.project = request.user.project_set.first()
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return error("wrong api key", 401)
|
return error("wrong api key", 401)
|
||||||
|
|
||||||
|
|||||||
25
hc/api/migrations/0054_auto_20190112_1427.py
Normal file
25
hc/api/migrations/0054_auto_20190112_1427.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-01-12 14:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0018_auto_20190112_1426'),
|
||||||
|
('api', '0053_check_subject'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='channel',
|
||||||
|
name='project',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.Project'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='check',
|
||||||
|
name='project',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.Project'),
|
||||||
|
),
|
||||||
|
]
|
||||||
23
hc/api/migrations/0055_auto_20190112_1427.py
Normal file
23
hc/api/migrations/0055_auto_20190112_1427.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-01-12 14:27
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def fill_project_id(apps, schema_editor):
|
||||||
|
Project = apps.get_model("accounts", "Project")
|
||||||
|
Check = apps.get_model("api", "Check")
|
||||||
|
Channel = apps.get_model("api", "Channel")
|
||||||
|
for project in Project.objects.all():
|
||||||
|
Check.objects.filter(user_id=project.owner_id).update(project=project)
|
||||||
|
Channel.objects.filter(user_id=project.owner_id).update(project=project)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('api', '0054_auto_20190112_1427'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(fill_project_id, migrations.RunPython.noop),
|
||||||
|
]
|
||||||
@ -12,6 +12,7 @@ from django.contrib.auth.models import User
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from hc.accounts.models import Project
|
||||||
from hc.api import transports
|
from hc.api import transports
|
||||||
from hc.lib import emails
|
from hc.lib import emails
|
||||||
import requests
|
import requests
|
||||||
@ -67,6 +68,7 @@ class Check(models.Model):
|
|||||||
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||||
desc = models.TextField(blank=True)
|
desc = models.TextField(blank=True)
|
||||||
user = models.ForeignKey(User, models.CASCADE)
|
user = models.ForeignKey(User, models.CASCADE)
|
||||||
|
project = models.ForeignKey(Project, models.CASCADE, null=True)
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
kind = models.CharField(max_length=10, default="simple",
|
kind = models.CharField(max_length=10, default="simple",
|
||||||
choices=CHECK_KINDS)
|
choices=CHECK_KINDS)
|
||||||
@ -262,6 +264,7 @@ class Channel(models.Model):
|
|||||||
name = models.CharField(max_length=100, blank=True)
|
name = models.CharField(max_length=100, blank=True)
|
||||||
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||||
user = models.ForeignKey(User, models.CASCADE)
|
user = models.ForeignKey(User, models.CASCADE)
|
||||||
|
project = models.ForeignKey(Project, models.CASCADE, null=True,)
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
kind = models.CharField(max_length=20, choices=CHANNEL_KINDS)
|
kind = models.CharField(max_length=20, choices=CHANNEL_KINDS)
|
||||||
value = models.TextField(blank=True)
|
value = models.TextField(blank=True)
|
||||||
|
|||||||
@ -47,6 +47,7 @@ class CreateCheckTestCase(BaseTestCase):
|
|||||||
self.assertEqual(check.tags, "bar,baz")
|
self.assertEqual(check.tags, "bar,baz")
|
||||||
self.assertEqual(check.timeout.total_seconds(), 3600)
|
self.assertEqual(check.timeout.total_seconds(), 3600)
|
||||||
self.assertEqual(check.grace.total_seconds(), 60)
|
self.assertEqual(check.grace.total_seconds(), 60)
|
||||||
|
self.assertEqual(check.project, self.project)
|
||||||
|
|
||||||
def test_it_handles_options(self):
|
def test_it_handles_options(self):
|
||||||
r = self.client.options(self.URL)
|
r = self.client.options(self.URL)
|
||||||
|
|||||||
@ -132,7 +132,7 @@ def create_check(request):
|
|||||||
if num_checks >= request.user.profile.check_limit:
|
if num_checks >= request.user.profile.check_limit:
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
check = Check(user=request.user)
|
check = Check(user=request.user, project=request.project)
|
||||||
created = True
|
created = True
|
||||||
|
|
||||||
_update(check, request.json)
|
_update(check, request.json)
|
||||||
|
|||||||
@ -9,7 +9,19 @@ class AddCheckTestCase(BaseTestCase):
|
|||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
r = self.client.post(url)
|
r = self.client.post(url)
|
||||||
self.assertRedirects(r, "/checks/")
|
self.assertRedirects(r, "/checks/")
|
||||||
assert Check.objects.count() == 1
|
check = Check.objects.get()
|
||||||
|
self.assertEqual(check.project, self.project)
|
||||||
|
|
||||||
|
def test_it_handles_unset_current_project(self):
|
||||||
|
self.profile.current_project = None
|
||||||
|
self.profile.save()
|
||||||
|
|
||||||
|
url = "/checks/add/"
|
||||||
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
r = self.client.post(url)
|
||||||
|
self.assertRedirects(r, "/checks/")
|
||||||
|
check = Check.objects.get()
|
||||||
|
self.assertEqual(check.project, self.project)
|
||||||
|
|
||||||
def test_team_access_works(self):
|
def test_team_access_works(self):
|
||||||
url = "/checks/add/"
|
url = "/checks/add/"
|
||||||
|
|||||||
@ -51,6 +51,7 @@ class AddDiscordTestCase(BaseTestCase):
|
|||||||
|
|
||||||
ch = Channel.objects.get()
|
ch = Channel.objects.get()
|
||||||
self.assertEqual(ch.discord_webhook_url, "foo")
|
self.assertEqual(ch.discord_webhook_url, "foo")
|
||||||
|
self.assertEqual(ch.project, self.project)
|
||||||
|
|
||||||
# Session should now be clean
|
# Session should now be clean
|
||||||
self.assertFalse("discord" in self.client.session)
|
self.assertFalse("discord" in self.client.session)
|
||||||
|
|||||||
@ -21,6 +21,7 @@ class AddPdTestCase(BaseTestCase):
|
|||||||
self.assertEqual(c.kind, "email")
|
self.assertEqual(c.kind, "email")
|
||||||
self.assertEqual(c.value, "alice@example.org")
|
self.assertEqual(c.value, "alice@example.org")
|
||||||
self.assertFalse(c.email_verified)
|
self.assertFalse(c.email_verified)
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
def test_team_access_works(self):
|
def test_team_access_works(self):
|
||||||
form = {"value": "bob@example.org"}
|
form = {"value": "bob@example.org"}
|
||||||
|
|||||||
@ -34,3 +34,4 @@ class AddHipChatTestCase(BaseTestCase):
|
|||||||
c = Channel.objects.get()
|
c = Channel.objects.get()
|
||||||
self.assertEqual(c.kind, "hipchat")
|
self.assertEqual(c.kind, "hipchat")
|
||||||
self.assertEqual(c.value, "{}")
|
self.assertEqual(c.value, "{}")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class AddOpsGenieTestCase(BaseTestCase):
|
|||||||
c = Channel.objects.get()
|
c = Channel.objects.get()
|
||||||
self.assertEqual(c.kind, "opsgenie")
|
self.assertEqual(c.kind, "opsgenie")
|
||||||
self.assertEqual(c.value, "123456")
|
self.assertEqual(c.value, "123456")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
def test_it_trims_whitespace(self):
|
def test_it_trims_whitespace(self):
|
||||||
form = {"value": " 123456 "}
|
form = {"value": " 123456 "}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class AddPagerTreeTestCase(BaseTestCase):
|
|||||||
c = Channel.objects.get()
|
c = Channel.objects.get()
|
||||||
self.assertEqual(c.kind, "pagertree")
|
self.assertEqual(c.kind, "pagertree")
|
||||||
self.assertEqual(c.value, "http://example.org")
|
self.assertEqual(c.value, "http://example.org")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
def test_it_rejects_bad_url(self):
|
def test_it_rejects_bad_url(self):
|
||||||
form = {"value": "not an URL"}
|
form = {"value": "not an URL"}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ class AddPdTestCase(BaseTestCase):
|
|||||||
c = Channel.objects.get()
|
c = Channel.objects.get()
|
||||||
self.assertEqual(c.kind, "pd")
|
self.assertEqual(c.kind, "pd")
|
||||||
self.assertEqual(c.pd_service_key, "123")
|
self.assertEqual(c.pd_service_key, "123")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
def test_it_validates_code(self):
|
def test_it_validates_code(self):
|
||||||
session = self.client.session
|
session = self.client.session
|
||||||
|
|||||||
@ -45,6 +45,7 @@ class AddPushbulletTestCase(BaseTestCase):
|
|||||||
|
|
||||||
ch = Channel.objects.get()
|
ch = Channel.objects.get()
|
||||||
self.assertEqual(ch.value, "test-token")
|
self.assertEqual(ch.value, "test-token")
|
||||||
|
self.assertEqual(ch.project, self.project)
|
||||||
|
|
||||||
# Session should now be clean
|
# Session should now be clean
|
||||||
self.assertFalse("pushbullet" in self.client.session)
|
self.assertFalse("pushbullet" in self.client.session)
|
||||||
|
|||||||
@ -43,9 +43,9 @@ class AddPushoverTestCase(BaseTestCase):
|
|||||||
r = self.client.get("/integrations/add_pushover/?%s" % params)
|
r = self.client.get("/integrations/add_pushover/?%s" % params)
|
||||||
self.assertEqual(r.status_code, 302)
|
self.assertEqual(r.status_code, 302)
|
||||||
|
|
||||||
channels = list(Channel.objects.all())
|
channel = Channel.objects.get()
|
||||||
assert len(channels) == 1
|
self.assertEqual(channel.value, "a|0|-1")
|
||||||
assert channels[0].value == "a|0|-1"
|
self.assertEqual(channel.project, self.project)
|
||||||
|
|
||||||
def test_it_validates_priority(self):
|
def test_it_validates_priority(self):
|
||||||
self.client.login(username="alice@example.org", password="password")
|
self.client.login(username="alice@example.org", password="password")
|
||||||
|
|||||||
@ -22,6 +22,7 @@ class AddSlackTestCase(BaseTestCase):
|
|||||||
c = Channel.objects.get()
|
c = Channel.objects.get()
|
||||||
self.assertEqual(c.kind, "slack")
|
self.assertEqual(c.kind, "slack")
|
||||||
self.assertEqual(c.value, "http://example.org")
|
self.assertEqual(c.value, "http://example.org")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
@override_settings(SLACK_CLIENT_ID=None)
|
@override_settings(SLACK_CLIENT_ID=None)
|
||||||
def test_it_rejects_bad_url(self):
|
def test_it_rejects_bad_url(self):
|
||||||
|
|||||||
@ -54,6 +54,7 @@ class AddSlackBtnTestCase(BaseTestCase):
|
|||||||
self.assertEqual(ch.slack_team, "foo")
|
self.assertEqual(ch.slack_team, "foo")
|
||||||
self.assertEqual(ch.slack_channel, "bar")
|
self.assertEqual(ch.slack_channel, "bar")
|
||||||
self.assertEqual(ch.slack_webhook_url, "http://example.org")
|
self.assertEqual(ch.slack_webhook_url, "http://example.org")
|
||||||
|
self.assertEqual(ch.project, self.project)
|
||||||
|
|
||||||
# Session should now be clean
|
# Session should now be clean
|
||||||
self.assertFalse("slack" in self.client.session)
|
self.assertFalse("slack" in self.client.session)
|
||||||
|
|||||||
@ -32,6 +32,7 @@ class AddSmsTestCase(BaseTestCase):
|
|||||||
self.assertEqual(c.kind, "sms")
|
self.assertEqual(c.kind, "sms")
|
||||||
self.assertEqual(c.sms_number, "+1234567890")
|
self.assertEqual(c.sms_number, "+1234567890")
|
||||||
self.assertEqual(c.name, "My Phone")
|
self.assertEqual(c.name, "My Phone")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
def test_it_rejects_bad_number(self):
|
def test_it_rejects_bad_number(self):
|
||||||
form = {"value": "not a phone number address"}
|
form = {"value": "not a phone number address"}
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from hc.api.models import Channel
|
from hc.api.models import Channel
|
||||||
from hc.test import BaseTestCase
|
from hc.test import BaseTestCase
|
||||||
@ -33,6 +31,7 @@ class AddTelegramTestCase(BaseTestCase):
|
|||||||
self.assertEqual(c.telegram_id, 123)
|
self.assertEqual(c.telegram_id, 123)
|
||||||
self.assertEqual(c.telegram_type, "group")
|
self.assertEqual(c.telegram_type, "group")
|
||||||
self.assertEqual(c.telegram_name, "My Group")
|
self.assertEqual(c.telegram_name, "My Group")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
@patch("hc.api.transports.requests.request")
|
@patch("hc.api.transports.requests.request")
|
||||||
def test_it_sends_invite(self, mock_get):
|
def test_it_sends_invite(self, mock_get):
|
||||||
|
|||||||
@ -20,6 +20,7 @@ class AddVictorOpsTestCase(BaseTestCase):
|
|||||||
c = Channel.objects.get()
|
c = Channel.objects.get()
|
||||||
self.assertEqual(c.kind, "victorops")
|
self.assertEqual(c.kind, "victorops")
|
||||||
self.assertEqual(c.value, "http://example.org")
|
self.assertEqual(c.value, "http://example.org")
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
def test_it_rejects_bad_url(self):
|
def test_it_rejects_bad_url(self):
|
||||||
form = {"value": "not an URL"}
|
form = {"value": "not an URL"}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ class AddWebhookTestCase(BaseTestCase):
|
|||||||
|
|
||||||
c = Channel.objects.get()
|
c = Channel.objects.get()
|
||||||
self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}')
|
self.assertEqual(c.value, '{"headers": {}, "post_data": "", "url_down": "http://foo.com", "url_up": "https://bar.com"}')
|
||||||
|
self.assertEqual(c.project, self.project)
|
||||||
|
|
||||||
def test_it_adds_webhook_using_team_access(self):
|
def test_it_adds_webhook_using_team_access(self):
|
||||||
form = {"url_down": "http://foo.com", "url_up": "https://bar.com"}
|
form = {"url_down": "http://foo.com", "url_up": "https://bar.com"}
|
||||||
|
|||||||
@ -249,7 +249,7 @@ def add_check(request):
|
|||||||
if num_checks >= request.team.check_limit:
|
if num_checks >= request.team.check_limit:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
check = Check(user=request.team.user)
|
check = Check(user=request.team.user, project=request.project)
|
||||||
check.save()
|
check.save()
|
||||||
|
|
||||||
check.assign_all_channels()
|
check.assign_all_channels()
|
||||||
@ -589,6 +589,7 @@ def add_email(request):
|
|||||||
form = AddEmailForm(request.POST)
|
form = AddEmailForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
channel = Channel(user=request.team.user, kind="email")
|
channel = Channel(user=request.team.user, kind="email")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = form.cleaned_data["value"]
|
channel.value = form.cleaned_data["value"]
|
||||||
channel.save()
|
channel.save()
|
||||||
|
|
||||||
@ -608,6 +609,7 @@ def add_webhook(request):
|
|||||||
form = AddWebhookForm(request.POST)
|
form = AddWebhookForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
channel = Channel(user=request.team.user, kind="webhook")
|
channel = Channel(user=request.team.user, kind="webhook")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = form.get_value()
|
channel.value = form.get_value()
|
||||||
channel.save()
|
channel.save()
|
||||||
|
|
||||||
@ -658,9 +660,8 @@ def add_pd(request, state=None):
|
|||||||
messages.warning(request, "PagerDuty setup was cancelled")
|
messages.warning(request, "PagerDuty setup was cancelled")
|
||||||
return redirect("hc-channels")
|
return redirect("hc-channels")
|
||||||
|
|
||||||
channel = Channel()
|
channel = Channel(kind="pd", project=request.project)
|
||||||
channel.user = request.team.user
|
channel.user = request.team.user
|
||||||
channel.kind = "pd"
|
|
||||||
channel.value = json.dumps({
|
channel.value = json.dumps({
|
||||||
"service_key": request.GET.get("service_key"),
|
"service_key": request.GET.get("service_key"),
|
||||||
"account": request.GET.get("account")
|
"account": request.GET.get("account")
|
||||||
@ -687,6 +688,7 @@ def add_pagertree(request):
|
|||||||
form = AddUrlForm(request.POST)
|
form = AddUrlForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
channel = Channel(user=request.team.user, kind="pagertree")
|
channel = Channel(user=request.team.user, kind="pagertree")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = form.cleaned_data["value"]
|
channel.value = form.cleaned_data["value"]
|
||||||
channel.save()
|
channel.save()
|
||||||
|
|
||||||
@ -707,6 +709,7 @@ def add_slack(request):
|
|||||||
form = AddUrlForm(request.POST)
|
form = AddUrlForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
channel = Channel(user=request.team.user, kind="slack")
|
channel = Channel(user=request.team.user, kind="slack")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = form.cleaned_data["value"]
|
channel.value = form.cleaned_data["value"]
|
||||||
channel.save()
|
channel.save()
|
||||||
|
|
||||||
@ -741,9 +744,8 @@ def add_slack_btn(request):
|
|||||||
|
|
||||||
doc = result.json()
|
doc = result.json()
|
||||||
if doc.get("ok"):
|
if doc.get("ok"):
|
||||||
channel = Channel()
|
channel = Channel(kind="slack", project=request.project)
|
||||||
channel.user = request.team.user
|
channel.user = request.team.user
|
||||||
channel.kind = "slack"
|
|
||||||
channel.value = result.text
|
channel.value = result.text
|
||||||
channel.save()
|
channel.save()
|
||||||
channel.assign_all_checks()
|
channel.assign_all_checks()
|
||||||
@ -765,7 +767,7 @@ def add_hipchat(request):
|
|||||||
messages.warning(request, "Something went wrong!")
|
messages.warning(request, "Something went wrong!")
|
||||||
return redirect("hc-channels")
|
return redirect("hc-channels")
|
||||||
|
|
||||||
channel = Channel(kind="hipchat")
|
channel = Channel(kind="hipchat", project=request.project)
|
||||||
channel.user = request.team.user
|
channel.user = request.team.user
|
||||||
channel.value = response.text
|
channel.value = response.text
|
||||||
channel.save()
|
channel.save()
|
||||||
@ -810,7 +812,7 @@ def add_pushbullet(request):
|
|||||||
|
|
||||||
doc = result.json()
|
doc = result.json()
|
||||||
if "access_token" in doc:
|
if "access_token" in doc:
|
||||||
channel = Channel(kind="pushbullet")
|
channel = Channel(kind="pushbullet", project=request.project)
|
||||||
channel.user = request.team.user
|
channel.user = request.team.user
|
||||||
channel.value = doc["access_token"]
|
channel.value = doc["access_token"]
|
||||||
channel.save()
|
channel.save()
|
||||||
@ -858,7 +860,7 @@ def add_discord(request):
|
|||||||
|
|
||||||
doc = result.json()
|
doc = result.json()
|
||||||
if "access_token" in doc:
|
if "access_token" in doc:
|
||||||
channel = Channel(kind="discord")
|
channel = Channel(kind="discord", project=request.project)
|
||||||
channel.user = request.team.user
|
channel.user = request.team.user
|
||||||
channel.value = result.text
|
channel.value = result.text
|
||||||
channel.save()
|
channel.save()
|
||||||
@ -933,6 +935,7 @@ def add_pushover(request):
|
|||||||
|
|
||||||
# Subscription
|
# Subscription
|
||||||
channel = Channel(user=request.team.user, kind="po")
|
channel = Channel(user=request.team.user, kind="po")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = "%s|%s|%s" % (key, prio, prio_up)
|
channel.value = "%s|%s|%s" % (key, prio, prio_up)
|
||||||
channel.save()
|
channel.save()
|
||||||
channel.assign_all_checks()
|
channel.assign_all_checks()
|
||||||
@ -955,6 +958,7 @@ def add_opsgenie(request):
|
|||||||
form = AddOpsGenieForm(request.POST)
|
form = AddOpsGenieForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
channel = Channel(user=request.team.user, kind="opsgenie")
|
channel = Channel(user=request.team.user, kind="opsgenie")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = form.cleaned_data["value"]
|
channel.value = form.cleaned_data["value"]
|
||||||
channel.save()
|
channel.save()
|
||||||
|
|
||||||
@ -973,6 +977,7 @@ def add_victorops(request):
|
|||||||
form = AddUrlForm(request.POST)
|
form = AddUrlForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
channel = Channel(user=request.team.user, kind="victorops")
|
channel = Channel(user=request.team.user, kind="victorops")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = form.cleaned_data["value"]
|
channel.value = form.cleaned_data["value"]
|
||||||
channel.save()
|
channel.save()
|
||||||
|
|
||||||
@ -1021,6 +1026,7 @@ def add_telegram(request):
|
|||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
channel = Channel(user=request.team.user, kind="telegram")
|
channel = Channel(user=request.team.user, kind="telegram")
|
||||||
|
channel.project = request.project
|
||||||
channel.value = json.dumps({
|
channel.value = json.dumps({
|
||||||
"id": chat_id,
|
"id": chat_id,
|
||||||
"type": chat_type,
|
"type": chat_type,
|
||||||
@ -1051,6 +1057,7 @@ def add_sms(request):
|
|||||||
form = AddSmsForm(request.POST)
|
form = AddSmsForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
channel = Channel(user=request.team.user, kind="sms")
|
channel = Channel(user=request.team.user, kind="sms")
|
||||||
|
channel.project = request.project
|
||||||
channel.name = form.cleaned_data["label"]
|
channel.name = form.cleaned_data["label"]
|
||||||
channel.value = json.dumps({
|
channel.value = json.dumps({
|
||||||
"value": form.cleaned_data["value"]
|
"value": form.cleaned_data["value"]
|
||||||
|
|||||||
10
hc/test.py
10
hc/test.py
@ -1,7 +1,7 @@
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from hc.accounts.models import Member, Profile
|
from hc.accounts.models import Member, Profile, Project
|
||||||
|
|
||||||
|
|
||||||
class BaseTestCase(TestCase):
|
class BaseTestCase(TestCase):
|
||||||
@ -14,8 +14,12 @@ class BaseTestCase(TestCase):
|
|||||||
self.alice.set_password("password")
|
self.alice.set_password("password")
|
||||||
self.alice.save()
|
self.alice.save()
|
||||||
|
|
||||||
|
self.project = Project(owner=self.alice, api_key="X" * 32)
|
||||||
|
self.project.save()
|
||||||
|
|
||||||
self.profile = Profile(user=self.alice, api_key="X" * 32)
|
self.profile = Profile(user=self.alice, api_key="X" * 32)
|
||||||
self.profile.sms_limit = 50
|
self.profile.sms_limit = 50
|
||||||
|
self.profile.current_project = self.project
|
||||||
self.profile.save()
|
self.profile.save()
|
||||||
|
|
||||||
# Bob is on Alice's team and should have access to her stuff
|
# Bob is on Alice's team and should have access to her stuff
|
||||||
@ -25,9 +29,11 @@ class BaseTestCase(TestCase):
|
|||||||
|
|
||||||
self.bobs_profile = Profile(user=self.bob)
|
self.bobs_profile = Profile(user=self.bob)
|
||||||
self.bobs_profile.current_team = self.profile
|
self.bobs_profile.current_team = self.profile
|
||||||
|
self.bobs_profile.current_project = self.project
|
||||||
self.bobs_profile.save()
|
self.bobs_profile.save()
|
||||||
|
|
||||||
Member.objects.create(team=self.profile, user=self.bob)
|
Member.objects.create(team=self.profile, user=self.bob,
|
||||||
|
project=self.project)
|
||||||
|
|
||||||
# Charlie should have no access to Alice's stuff
|
# Charlie should have no access to Alice's stuff
|
||||||
self.charlie = User(username="charlie", email="charlie@example.org")
|
self.charlie = User(username="charlie", email="charlie@example.org")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user