Browse Source

Project model. cc: #183

pull/214/head
Pēteris Caune 6 years ago
parent
commit
1c69cf7f89
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
34 changed files with 283 additions and 32 deletions
  1. +2
    -0
      CHANGELOG.md
  2. +10
    -1
      hc/accounts/admin.py
  3. +4
    -0
      hc/accounts/middleware.py
  4. +38
    -0
      hc/accounts/migrations/0017_auto_20190112_1426.py
  5. +37
    -0
      hc/accounts/migrations/0018_auto_20190112_1426.py
  6. +15
    -3
      hc/accounts/models.py
  7. +1
    -0
      hc/accounts/tests/test_close_account.py
  8. +20
    -5
      hc/accounts/tests/test_profile.py
  9. +12
    -2
      hc/accounts/tests/test_signup.py
  10. +6
    -0
      hc/accounts/tests/test_switch_team.py
  11. +31
    -4
      hc/accounts/views.py
  12. +2
    -0
      hc/api/decorators.py
  13. +25
    -0
      hc/api/migrations/0054_auto_20190112_1427.py
  14. +23
    -0
      hc/api/migrations/0055_auto_20190112_1427.py
  15. +3
    -0
      hc/api/models.py
  16. +1
    -0
      hc/api/tests/test_create_check.py
  17. +1
    -1
      hc/api/views.py
  18. +13
    -1
      hc/front/tests/test_add_check.py
  19. +1
    -0
      hc/front/tests/test_add_discord.py
  20. +1
    -0
      hc/front/tests/test_add_email.py
  21. +1
    -0
      hc/front/tests/test_add_hipchat.py
  22. +1
    -0
      hc/front/tests/test_add_opsgenie.py
  23. +1
    -0
      hc/front/tests/test_add_pagertree.py
  24. +1
    -0
      hc/front/tests/test_add_pd.py
  25. +1
    -0
      hc/front/tests/test_add_pushbullet.py
  26. +3
    -3
      hc/front/tests/test_add_pushover.py
  27. +1
    -0
      hc/front/tests/test_add_slack.py
  28. +1
    -0
      hc/front/tests/test_add_slack_btn.py
  29. +1
    -0
      hc/front/tests/test_add_sms.py
  30. +1
    -2
      hc/front/tests/test_add_telegram.py
  31. +1
    -0
      hc/front/tests/test_add_victorops.py
  32. +1
    -0
      hc/front/tests/test_add_webhook.py
  33. +15
    -8
      hc/front/views.py
  34. +8
    -2
      hc/test.py

+ 2
- 0
CHANGELOG.md View File

@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file.
- Database schema: add Ping.kind field
- Database schema: remove Ping.start and Ping.fail fields
- Add "Email Settings..." dialog and "Subject Must Contain" setting
- Database schema: add the Project model
## 1.4.0 - 2018-12-25


+ 10
- 1
hc/accounts/admin.py View File

@ -5,7 +5,7 @@ from django.db.models import Count
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.safestring import mark_safe
from hc.accounts.models import Profile
from hc.accounts.models import Profile, Project
class Fieldset:
@ -85,6 +85,15 @@ class ProfileAdmin(admin.ModelAdmin):
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):
actions = ["send_report"]
list_display = ('id', 'email', 'date_joined', 'last_login', 'engagement',


+ 4
- 0
hc/accounts/middleware.py View File

@ -16,4 +16,8 @@ class TeamAccessMiddleware(object):
request.profile = Profile.objects.for_user(request.user)
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)

+ 38
- 0
hc/accounts/migrations/0017_auto_20190112_1426.py View 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
- 0
hc/accounts/migrations/0018_auto_20190112_1426.py View 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),
]

+ 15
- 3
hc/accounts/models.py View File

@ -1,6 +1,7 @@
from base64 import urlsafe_b64encode
import os
from datetime import timedelta
import os
import uuid
from django.conf import settings
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_readonly = models.CharField(max_length=128, blank=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)
sms_limit = 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
def invite(self, user):
member = Member(team=self, user=user)
member.save()
for project in self.user.project_set.all():
member = Member(team=self, user=user, project=project)
member.save()
# Switch the invited user over to the new team so they
# 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"))
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):
team = models.ForeignKey(Profile, models.CASCADE)
user = models.ForeignKey(User, models.CASCADE, related_name="memberships")
project = models.ForeignKey(Project, models.CASCADE, null=True)

+ 1
- 0
hc/accounts/tests/test_close_account.py View File

@ -27,6 +27,7 @@ class CloseAccountTestCase(BaseTestCase):
# Bob's current team should now be None
self.bobs_profile.refresh_from_db()
self.assertIsNone(self.bobs_profile.current_team)
self.assertIsNone(self.bobs_profile.current_project)
# Check should be gone
self.assertFalse(Check.objects.exists())


+ 20
- 5
hc/accounts/tests/test_profile.py View File

@ -39,6 +39,9 @@ class ProfileTestCase(BaseTestCase):
self.assertTrue(len(api_key) > 10)
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):
self.profile.api_key_readonly = "R" * 32
self.profile.save()
@ -53,6 +56,9 @@ class ProfileTestCase(BaseTestCase):
self.assertEqual(self.profile.api_key, "")
self.assertEqual(self.profile.api_key_readonly, "")
self.project.refresh_from_db()
self.assertEqual(self.project.api_key, "")
def test_it_sends_report(self):
check = Check(name="Test Check", user=self.alice)
check.last_ping = now()
@ -126,12 +132,16 @@ class ProfileTestCase(BaseTestCase):
r = self.client.post("/accounts/profile/", form)
self.assertEqual(r.status_code, 200)
member_emails = set()
for member in self.profile.member_set.all():
member_emails.add(member.user.email)
members = self.profile.member_set.all()
self.assertEqual(members.count(), 2)
self.assertEqual(len(member_emails), 2)
self.assertTrue("[email protected]" in member_emails)
frank_found = False
for member in members.all():
self.assertEqual(member.project, self.project)
if member.user.email == "[email protected]":
frank_found = True
self.assertTrue(frank_found)
# And an email should have been sent
subj = ('You have been invited to join'
@ -159,6 +169,7 @@ class ProfileTestCase(BaseTestCase):
self.bobs_profile.refresh_from_db()
self.assertEqual(self.bobs_profile.current_team, None)
self.assertEqual(self.bobs_profile.current_project, None)
def test_it_sets_team_name(self):
self.client.login(username="[email protected]", password="password")
@ -170,6 +181,9 @@ class ProfileTestCase(BaseTestCase):
self.profile.refresh_from_db()
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):
self.client.login(username="[email protected]", password="password")
@ -179,6 +193,7 @@ class ProfileTestCase(BaseTestCase):
# to user's default team.
self.bobs_profile.refresh_from_db()
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):
self.client.login(username="[email protected]", password="password")


+ 12
- 2
hc/accounts/tests/test_signup.py View File

@ -2,7 +2,8 @@ from django.contrib.auth.models import User
from django.core import mail
from django.test import TestCase
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
@ -15,16 +16,25 @@ class SignupTestCase(TestCase):
self.assertContains(r, "Account created")
# An user should have been created
self.assertEqual(User.objects.count(), 1)
user = User.objects.get()
# And email sent
self.assertEqual(len(mail.outbox), 1)
subject = "Log in to %s" % settings.SITE_NAME
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
check = Check.objects.get()
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)
def test_it_obeys_registration_open(self):


+ 6
- 0
hc/accounts/tests/test_switch_team.py View File

@ -5,6 +5,9 @@ from hc.api.models import Check
class SwitchTeamTestCase(BaseTestCase):
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.save()
@ -15,6 +18,9 @@ class SwitchTeamTestCase(BaseTestCase):
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):
self.client.login(username="[email protected]", password="password")


+ 31
- 4
hc/accounts/views.py View File

@ -21,7 +21,7 @@ from hc.accounts.forms import (ChangeEmailForm, EmailPasswordForm,
ReportSettingsForm, SetPasswordForm,
TeamNameForm, AvailableEmailForm,
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.lib.badges import get_badge_url
from hc.payments.models import Subscription
@ -49,14 +49,19 @@ def _make_user(email):
user.set_unusable_password()
user.save()
project = Project(owner=user)
project.save()
# Ensure a profile gets created
Profile.objects.for_user(user)
profile = Profile.objects.for_user(user)
profile.current_project = project
profile.save()
check = Check(user=user)
check = Check(user=user, project=project)
check.name = "My First Check"
check.save()
channel = Channel(user=user)
channel = Channel(user=user, project=project)
channel.kind = "email"
channel.value = email
channel.email_verified = True
@ -72,7 +77,10 @@ def _ensure_own_team(request):
if request.team != request.profile:
request.team = request.profile
request.project = request.user.project_set.first()
request.profile.current_team = request.profile
request.profile.current_project = request.project
request.profile.save()
@ -200,6 +208,12 @@ def profile(request):
return redirect("hc-link-sent")
elif "create_api_keys" in request.POST:
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["api_keys_created"] = True
ctx["api_status"] = "success"
@ -208,6 +222,12 @@ def profile(request):
profile.api_key = ""
profile.api_key_readonly = ""
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_status"] = "info"
elif "show_api_keys" in request.POST:
@ -236,6 +256,7 @@ def profile(request):
email = form.cleaned_data["email"]
farewell_user = User.objects.get(email=email)
farewell_user.profile.current_team = None
farewell_user.profile.current_project = None
farewell_user.profile.save()
Member.objects.filter(team=profile,
@ -248,6 +269,11 @@ def profile(request):
if form.is_valid():
profile.team_name = form.cleaned_data["team_name"]
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_status"] = "success"
@ -427,6 +453,7 @@ def switch_team(request, target_username):
return HttpResponseForbidden()
request.profile.current_team = target_team
request.profile.current_project = target_team.user.project_set.first()
request.profile.save()
return redirect("hc-checks")


+ 2
- 0
hc/api/decorators.py View File

@ -24,6 +24,7 @@ def authorize(f):
try:
request.user = User.objects.get(profile__api_key=api_key)
request.project = request.user.project_set.first()
except User.DoesNotExist:
return error("wrong api key", 401)
@ -46,6 +47,7 @@ def authorize_read(f):
read_key_match = Q(profile__api_key_readonly=api_key)
try:
request.user = User.objects.get(write_key_match | read_key_match)
request.project = request.user.project_set.first()
except User.DoesNotExist:
return error("wrong api key", 401)


+ 25
- 0
hc/api/migrations/0054_auto_20190112_1427.py View 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
- 0
hc/api/migrations/0055_auto_20190112_1427.py View 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),
]

+ 3
- 0
hc/api/models.py View File

@ -12,6 +12,7 @@ from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
from django.utils import timezone
from hc.accounts.models import Project
from hc.api import transports
from hc.lib import emails
import requests
@ -67,6 +68,7 @@ class Check(models.Model):
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
desc = models.TextField(blank=True)
user = models.ForeignKey(User, models.CASCADE)
project = models.ForeignKey(Project, models.CASCADE, null=True)
created = models.DateTimeField(auto_now_add=True)
kind = models.CharField(max_length=10, default="simple",
choices=CHECK_KINDS)
@ -262,6 +264,7 @@ class Channel(models.Model):
name = models.CharField(max_length=100, blank=True)
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
user = models.ForeignKey(User, models.CASCADE)
project = models.ForeignKey(Project, models.CASCADE, null=True,)
created = models.DateTimeField(auto_now_add=True)
kind = models.CharField(max_length=20, choices=CHANNEL_KINDS)
value = models.TextField(blank=True)


+ 1
- 0
hc/api/tests/test_create_check.py View File

@ -47,6 +47,7 @@ class CreateCheckTestCase(BaseTestCase):
self.assertEqual(check.tags, "bar,baz")
self.assertEqual(check.timeout.total_seconds(), 3600)
self.assertEqual(check.grace.total_seconds(), 60)
self.assertEqual(check.project, self.project)
def test_it_handles_options(self):
r = self.client.options(self.URL)


+ 1
- 1
hc/api/views.py View File

@ -132,7 +132,7 @@ def create_check(request):
if num_checks >= request.user.profile.check_limit:
return HttpResponseForbidden()
check = Check(user=request.user)
check = Check(user=request.user, project=request.project)
created = True
_update(check, request.json)


+ 13
- 1
hc/front/tests/test_add_check.py View File

@ -9,7 +9,19 @@ class AddCheckTestCase(BaseTestCase):
self.client.login(username="[email protected]", password="password")
r = self.client.post(url)
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="[email protected]", 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):
url = "/checks/add/"


+ 1
- 0
hc/front/tests/test_add_discord.py View File

@ -51,6 +51,7 @@ class AddDiscordTestCase(BaseTestCase):
ch = Channel.objects.get()
self.assertEqual(ch.discord_webhook_url, "foo")
self.assertEqual(ch.project, self.project)
# Session should now be clean
self.assertFalse("discord" in self.client.session)


+ 1
- 0
hc/front/tests/test_add_email.py View File

@ -21,6 +21,7 @@ class AddPdTestCase(BaseTestCase):
self.assertEqual(c.kind, "email")
self.assertEqual(c.value, "[email protected]")
self.assertFalse(c.email_verified)
self.assertEqual(c.project, self.project)
def test_team_access_works(self):
form = {"value": "[email protected]"}


+ 1
- 0
hc/front/tests/test_add_hipchat.py View File

@ -34,3 +34,4 @@ class AddHipChatTestCase(BaseTestCase):
c = Channel.objects.get()
self.assertEqual(c.kind, "hipchat")
self.assertEqual(c.value, "{}")
self.assertEqual(c.project, self.project)

+ 1
- 0
hc/front/tests/test_add_opsgenie.py View File

@ -20,6 +20,7 @@ class AddOpsGenieTestCase(BaseTestCase):
c = Channel.objects.get()
self.assertEqual(c.kind, "opsgenie")
self.assertEqual(c.value, "123456")
self.assertEqual(c.project, self.project)
def test_it_trims_whitespace(self):
form = {"value": " 123456 "}


+ 1
- 0
hc/front/tests/test_add_pagertree.py View File

@ -20,6 +20,7 @@ class AddPagerTreeTestCase(BaseTestCase):
c = Channel.objects.get()
self.assertEqual(c.kind, "pagertree")
self.assertEqual(c.value, "http://example.org")
self.assertEqual(c.project, self.project)
def test_it_rejects_bad_url(self):
form = {"value": "not an URL"}


+ 1
- 0
hc/front/tests/test_add_pd.py View File

@ -25,6 +25,7 @@ class AddPdTestCase(BaseTestCase):
c = Channel.objects.get()
self.assertEqual(c.kind, "pd")
self.assertEqual(c.pd_service_key, "123")
self.assertEqual(c.project, self.project)
def test_it_validates_code(self):
session = self.client.session


+ 1
- 0
hc/front/tests/test_add_pushbullet.py View File

@ -45,6 +45,7 @@ class AddPushbulletTestCase(BaseTestCase):
ch = Channel.objects.get()
self.assertEqual(ch.value, "test-token")
self.assertEqual(ch.project, self.project)
# Session should now be clean
self.assertFalse("pushbullet" in self.client.session)


+ 3
- 3
hc/front/tests/test_add_pushover.py View File

@ -43,9 +43,9 @@ class AddPushoverTestCase(BaseTestCase):
r = self.client.get("/integrations/add_pushover/?%s" % params)
self.assertEqual(r.status_code, 302)
channels = list(Channel.objects.all())
assert len(channels) == 1
assert channels[0].value == "a|0|-1"
channel = Channel.objects.get()
self.assertEqual(channel.value, "a|0|-1")
self.assertEqual(channel.project, self.project)
def test_it_validates_priority(self):
self.client.login(username="[email protected]", password="password")


+ 1
- 0
hc/front/tests/test_add_slack.py View File

@ -22,6 +22,7 @@ class AddSlackTestCase(BaseTestCase):
c = Channel.objects.get()
self.assertEqual(c.kind, "slack")
self.assertEqual(c.value, "http://example.org")
self.assertEqual(c.project, self.project)
@override_settings(SLACK_CLIENT_ID=None)
def test_it_rejects_bad_url(self):


+ 1
- 0
hc/front/tests/test_add_slack_btn.py View File

@ -54,6 +54,7 @@ class AddSlackBtnTestCase(BaseTestCase):
self.assertEqual(ch.slack_team, "foo")
self.assertEqual(ch.slack_channel, "bar")
self.assertEqual(ch.slack_webhook_url, "http://example.org")
self.assertEqual(ch.project, self.project)
# Session should now be clean
self.assertFalse("slack" in self.client.session)


+ 1
- 0
hc/front/tests/test_add_sms.py View File

@ -32,6 +32,7 @@ class AddSmsTestCase(BaseTestCase):
self.assertEqual(c.kind, "sms")
self.assertEqual(c.sms_number, "+1234567890")
self.assertEqual(c.name, "My Phone")
self.assertEqual(c.project, self.project)
def test_it_rejects_bad_number(self):
form = {"value": "not a phone number address"}


+ 1
- 2
hc/front/tests/test_add_telegram.py View File

@ -1,5 +1,3 @@
import json
from django.core import signing
from hc.api.models import Channel
from hc.test import BaseTestCase
@ -33,6 +31,7 @@ class AddTelegramTestCase(BaseTestCase):
self.assertEqual(c.telegram_id, 123)
self.assertEqual(c.telegram_type, "group")
self.assertEqual(c.telegram_name, "My Group")
self.assertEqual(c.project, self.project)
@patch("hc.api.transports.requests.request")
def test_it_sends_invite(self, mock_get):


+ 1
- 0
hc/front/tests/test_add_victorops.py View File

@ -20,6 +20,7 @@ class AddVictorOpsTestCase(BaseTestCase):
c = Channel.objects.get()
self.assertEqual(c.kind, "victorops")
self.assertEqual(c.value, "http://example.org")
self.assertEqual(c.project, self.project)
def test_it_rejects_bad_url(self):
form = {"value": "not an URL"}


+ 1
- 0
hc/front/tests/test_add_webhook.py View File

@ -19,6 +19,7 @@ class AddWebhookTestCase(BaseTestCase):
c = Channel.objects.get()
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):
form = {"url_down": "http://foo.com", "url_up": "https://bar.com"}


+ 15
- 8
hc/front/views.py View File

@ -249,7 +249,7 @@ def add_check(request):
if num_checks >= request.team.check_limit:
return HttpResponseBadRequest()
check = Check(user=request.team.user)
check = Check(user=request.team.user, project=request.project)
check.save()
check.assign_all_channels()
@ -589,6 +589,7 @@ def add_email(request):
form = AddEmailForm(request.POST)
if form.is_valid():
channel = Channel(user=request.team.user, kind="email")
channel.project = request.project
channel.value = form.cleaned_data["value"]
channel.save()
@ -608,6 +609,7 @@ def add_webhook(request):
form = AddWebhookForm(request.POST)
if form.is_valid():
channel = Channel(user=request.team.user, kind="webhook")
channel.project = request.project
channel.value = form.get_value()
channel.save()
@ -658,9 +660,8 @@ def add_pd(request, state=None):
messages.warning(request, "PagerDuty setup was cancelled")
return redirect("hc-channels")
channel = Channel()
channel = Channel(kind="pd", project=request.project)
channel.user = request.team.user
channel.kind = "pd"
channel.value = json.dumps({
"service_key": request.GET.get("service_key"),
"account": request.GET.get("account")
@ -687,6 +688,7 @@ def add_pagertree(request):
form = AddUrlForm(request.POST)
if form.is_valid():
channel = Channel(user=request.team.user, kind="pagertree")
channel.project = request.project
channel.value = form.cleaned_data["value"]
channel.save()
@ -707,6 +709,7 @@ def add_slack(request):
form = AddUrlForm(request.POST)
if form.is_valid():
channel = Channel(user=request.team.user, kind="slack")
channel.project = request.project
channel.value = form.cleaned_data["value"]
channel.save()
@ -741,9 +744,8 @@ def add_slack_btn(request):
doc = result.json()
if doc.get("ok"):
channel = Channel()
channel = Channel(kind="slack", project=request.project)
channel.user = request.team.user
channel.kind = "slack"
channel.value = result.text
channel.save()
channel.assign_all_checks()
@ -765,7 +767,7 @@ def add_hipchat(request):
messages.warning(request, "Something went wrong!")
return redirect("hc-channels")
channel = Channel(kind="hipchat")
channel = Channel(kind="hipchat", project=request.project)
channel.user = request.team.user
channel.value = response.text
channel.save()
@ -810,7 +812,7 @@ def add_pushbullet(request):
doc = result.json()
if "access_token" in doc:
channel = Channel(kind="pushbullet")
channel = Channel(kind="pushbullet", project=request.project)
channel.user = request.team.user
channel.value = doc["access_token"]
channel.save()
@ -858,7 +860,7 @@ def add_discord(request):
doc = result.json()
if "access_token" in doc:
channel = Channel(kind="discord")
channel = Channel(kind="discord", project=request.project)
channel.user = request.team.user
channel.value = result.text
channel.save()
@ -933,6 +935,7 @@ def add_pushover(request):
# Subscription
channel = Channel(user=request.team.user, kind="po")
channel.project = request.project
channel.value = "%s|%s|%s" % (key, prio, prio_up)
channel.save()
channel.assign_all_checks()
@ -955,6 +958,7 @@ def add_opsgenie(request):
form = AddOpsGenieForm(request.POST)
if form.is_valid():
channel = Channel(user=request.team.user, kind="opsgenie")
channel.project = request.project
channel.value = form.cleaned_data["value"]
channel.save()
@ -973,6 +977,7 @@ def add_victorops(request):
form = AddUrlForm(request.POST)
if form.is_valid():
channel = Channel(user=request.team.user, kind="victorops")
channel.project = request.project
channel.value = form.cleaned_data["value"]
channel.save()
@ -1021,6 +1026,7 @@ def add_telegram(request):
if request.method == "POST":
channel = Channel(user=request.team.user, kind="telegram")
channel.project = request.project
channel.value = json.dumps({
"id": chat_id,
"type": chat_type,
@ -1051,6 +1057,7 @@ def add_sms(request):
form = AddSmsForm(request.POST)
if form.is_valid():
channel = Channel(user=request.team.user, kind="sms")
channel.project = request.project
channel.name = form.cleaned_data["label"]
channel.value = json.dumps({
"value": form.cleaned_data["value"]


+ 8
- 2
hc/test.py View File

@ -1,7 +1,7 @@
from django.contrib.auth.models import User
from django.test import TestCase
from hc.accounts.models import Member, Profile
from hc.accounts.models import Member, Profile, Project
class BaseTestCase(TestCase):
@ -14,8 +14,12 @@ class BaseTestCase(TestCase):
self.alice.set_password("password")
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.sms_limit = 50
self.profile.current_project = self.project
self.profile.save()
# 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.current_team = self.profile
self.bobs_profile.current_project = self.project
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
self.charlie = User(username="charlie", email="[email protected]")


Loading…
Cancel
Save