mirror of
https://github.com/healthchecks/healthchecks.git
synced 2025-04-07 22:25:35 +00:00
Send an "Ownership Transfer Request" email notification.
This commit is contained in:
parent
da954000fd
commit
57da17b8e2
10 changed files with 72 additions and 2 deletions
|
@ -6,7 +6,8 @@ All notable changes to this project will be documented in this file.
|
||||||
### Improvements
|
### Improvements
|
||||||
- Rate limiting for Telegram notifications (10 notifications per chat per minute)
|
- Rate limiting for Telegram notifications (10 notifications per chat per minute)
|
||||||
- Use Slack V2 OAuth flow
|
- Use Slack V2 OAuth flow
|
||||||
- "Edit" function for webhook integrations (#176)
|
- Users can edit their existing webhook integrations (#176)
|
||||||
|
- Add a "Transfer Ownership" feature in Project Settings
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
- "Get a single check" API call now supports read-only API keys (#346)
|
- "Get a single check" API call now supports read-only API keys (#346)
|
||||||
|
|
|
@ -96,6 +96,19 @@ class Profile(models.Model):
|
||||||
}
|
}
|
||||||
emails.login(self.user.email, ctx)
|
emails.login(self.user.email, ctx)
|
||||||
|
|
||||||
|
def send_transfer_request(self, project):
|
||||||
|
token = self.prepare_token("login")
|
||||||
|
settings_path = reverse("hc-project-settings", args=[project.code])
|
||||||
|
path = reverse("hc-check-token", args=[self.user.username, token])
|
||||||
|
path += "?next=%s" % settings_path
|
||||||
|
|
||||||
|
ctx = {
|
||||||
|
"button_text": "Project Settings",
|
||||||
|
"button_url": settings.SITE_ROOT + path,
|
||||||
|
"project": project,
|
||||||
|
}
|
||||||
|
emails.transfer_request(self.user.email, ctx)
|
||||||
|
|
||||||
def send_set_password_link(self):
|
def send_set_password_link(self):
|
||||||
token = self.prepare_token("set-password")
|
token = self.prepare_token("set-password")
|
||||||
path = reverse("hc-set-password", args=[token])
|
path = reverse("hc-set-password", args=[token])
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django.core import mail
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from hc.api.models import Check
|
from hc.api.models import Check
|
||||||
from hc.test import BaseTestCase
|
from hc.test import BaseTestCase
|
||||||
|
@ -21,6 +22,11 @@ class ProjectTestCase(BaseTestCase):
|
||||||
self.bobs_membership.refresh_from_db()
|
self.bobs_membership.refresh_from_db()
|
||||||
self.assertIsNotNone(self.bobs_membership.transfer_request_date)
|
self.assertIsNotNone(self.bobs_membership.transfer_request_date)
|
||||||
|
|
||||||
|
# Bob should receive an email notification
|
||||||
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
|
body = mail.outbox[0].body
|
||||||
|
self.assertTrue("/?next=" + self.url in body)
|
||||||
|
|
||||||
def test_transfer_project_checks_ownership(self):
|
def test_transfer_project_checks_ownership(self):
|
||||||
self.client.login(username="bob@example.org", password="password")
|
self.client.login(username="bob@example.org", password="password")
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ NEXT_WHITELIST = (
|
||||||
"hc-add-slack",
|
"hc-add-slack",
|
||||||
"hc-add-pushover",
|
"hc-add-pushover",
|
||||||
"hc-add-telegram",
|
"hc-add-telegram",
|
||||||
|
"hc-project-settings",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -350,7 +351,8 @@ def project(request, code):
|
||||||
ctx["transfer_initiated"] = True
|
ctx["transfer_initiated"] = True
|
||||||
ctx["transfer_status"] = "success"
|
ctx["transfer_status"] = "success"
|
||||||
|
|
||||||
# FIXME send email
|
profile = Profile.objects.get(user__email=email)
|
||||||
|
profile.send_transfer_request(project)
|
||||||
|
|
||||||
elif "cancel_transfer" in request.POST:
|
elif "cancel_transfer" in request.POST:
|
||||||
if not is_owner:
|
if not is_owner:
|
||||||
|
|
|
@ -41,6 +41,10 @@ def login(to, ctx):
|
||||||
send("login", to, ctx)
|
send("login", to, ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def transfer_request(to, ctx):
|
||||||
|
send("transfer-request", to, ctx)
|
||||||
|
|
||||||
|
|
||||||
def set_password(to, ctx):
|
def set_password(to, ctx):
|
||||||
send("set-password", to, ctx)
|
send("set-password", to, ctx)
|
||||||
|
|
||||||
|
|
|
@ -460,6 +460,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
|
{% if project.team %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="update-name-input" class="col-sm-4 control-label">
|
<label for="update-name-input" class="col-sm-4 control-label">
|
||||||
Choose owner
|
Choose owner
|
||||||
|
@ -476,6 +477,13 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p>
|
||||||
|
This project currently has no team members.
|
||||||
|
To transfer the ownership of this project, please start by
|
||||||
|
inviting the new owner as a team member.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
|
|
@ -159,6 +159,8 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<li role="separator" class="divider"></li>
|
<li role="separator" class="divider"></li>
|
||||||
|
<li class="dropdown-header">{{ request.user.email }}</li>
|
||||||
|
|
||||||
<li><a href="{% url 'hc-profile' %}">Account Settings</a></li>
|
<li><a href="{% url 'hc-profile' %}">Account Settings</a></li>
|
||||||
<li><a href="{% url 'hc-logout' %}">Log Out</a></li>
|
<li><a href="{% url 'hc-logout' %}">Log Out</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
19
templates/emails/transfer-request-body-html.html
Normal file
19
templates/emails/transfer-request-body-html.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{% extends "emails/base.html" %}
|
||||||
|
{% load hc_extras %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
Hello,
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<strong>{{ project.owner.email }}</strong> would like to transfer the ownership of
|
||||||
|
their project
|
||||||
|
{% if project.name %}<strong>{{ project.name }}</strong>{% endif %} to you.
|
||||||
|
<br /><br />
|
||||||
|
To accept or reject this request, please visit the project's Settings
|
||||||
|
page:
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content_more %}
|
||||||
|
Thanks,<br>
|
||||||
|
The {% site_name %} Team
|
||||||
|
{% endblock %}
|
14
templates/emails/transfer-request-body-text.html
Normal file
14
templates/emails/transfer-request-body-text.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{% load hc_extras %}
|
||||||
|
{% block content %}Hello,
|
||||||
|
|
||||||
|
{{ project.owner.email }} would like to transfer the ownership of their
|
||||||
|
project {% if project.name %}"{{ project.name }}"{% endif %} to you.
|
||||||
|
|
||||||
|
To accept or reject this request, please visit the project's Settings
|
||||||
|
page:
|
||||||
|
|
||||||
|
{{ button_url }}
|
||||||
|
|
||||||
|
Thanks,
|
||||||
|
The {% site_name %} Team
|
||||||
|
{% endblock %}
|
1
templates/emails/transfer-request-subject.html
Normal file
1
templates/emails/transfer-request-subject.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Ownership Transfer Request
|
Loading…
Add table
Reference in a new issue