From cf6442cec2f7b0e6510b2d3befa23d3471ed551c Mon Sep 17 00:00:00 2001 From: Son Date: Wed, 10 Mar 2021 22:56:12 +0100 Subject: [PATCH] Add PATCH /api/custom_domains/:custom_domain_id --- app/api/views/custom_domain.py | 72 ++++++++++++++++++++++++++++++++- docs/api.md | 15 +++++++ tests/api/test_custom_domain.py | 41 ++++++++++++++++++- 3 files changed, 125 insertions(+), 3 deletions(-) diff --git a/app/api/views/custom_domain.py b/app/api/views/custom_domain.py index 3300a17e..7eab2638 100644 --- a/app/api/views/custom_domain.py +++ b/app/api/views/custom_domain.py @@ -1,8 +1,9 @@ -from flask import g +from flask import g, request from flask import jsonify from app.api.base import api_bp, require_api_auth -from app.models import CustomDomain, DomainDeletedAlias +from app.extensions import db +from app.models import CustomDomain, DomainDeletedAlias, Mailbox, DomainMailbox def custom_domain_to_dict(custom_domain: CustomDomain): @@ -52,3 +53,70 @@ def get_custom_domain_trash(custom_domain_id: int): for dda in domain_deleted_aliases ] ) + + +@api_bp.route("/custom_domains/", methods=["PATCH"]) +@require_api_auth +def update_custom_domain(custom_domain_id): + """ + Update alias note + Input: + custom_domain_id: in url + In body: + catch_all (optional): boolean + random_prefix_generation (optional): boolean + name (optional): in body + mailbox_ids (optional): array of mailbox_id + Output: + 200 + """ + data = request.get_json() + if not data: + return jsonify(error="request body cannot be empty"), 400 + + user = g.user + custom_domain: CustomDomain = CustomDomain.get(custom_domain_id) + + if not custom_domain or custom_domain.user_id != user.id: + return jsonify(error="Forbidden"), 403 + + changed = False + if "catch_all" in data: + catch_all = data.get("catch_all") + custom_domain.catch_all = catch_all + changed = True + + if "random_prefix_generation" in data: + random_prefix_generation = data.get("random_prefix_generation") + custom_domain.random_prefix_generation = random_prefix_generation + changed = True + + if "name" in data: + name = data.get("name") + custom_domain.name = name + changed = True + + if "mailbox_ids" in data: + mailbox_ids = [int(m_id) for m_id in data.get("mailbox_ids")] + if mailbox_ids: + # check if mailbox is not tempered with + mailboxes = [] + for mailbox_id in mailbox_ids: + mailbox = Mailbox.get(mailbox_id) + if not mailbox or mailbox.user_id != user.id or not mailbox.verified: + return jsonify(error="Forbidden"), 400 + mailboxes.append(mailbox) + + # first remove all existing domain-mailboxes links + DomainMailbox.query.filter_by(domain_id=custom_domain.id).delete() + db.session.flush() + + for mailbox in mailboxes: + DomainMailbox.create(domain_id=custom_domain.id, mailbox_id=mailbox.id) + + changed = True + + if changed: + db.session.commit() + + return jsonify(ok=True), 200 diff --git a/docs/api.md b/docs/api.md index 4fd5952b..cf892ae8 100644 --- a/docs/api.md +++ b/docs/api.md @@ -670,6 +670,21 @@ List of custom domains. ] ``` +#### PATCH /api/custom_domains/:custom_domain_id + +Update alias info. + +Input: +- `Authentication` header that contains the api key +- `custom_domain_id` in url. +- (optional) `catch_all`: boolean, in request body +- (optional) `random_prefix_generation`: boolean, in request body +- (optional) `name`: text, in request body +- (optional) `mailbox_ids`: array of mailbox id, in request body + +Output: +If success, return 200 + #### GET /api/custom_domains/:custom_domain_id/trash Get deleted alias for a custom domain diff --git a/tests/api/test_custom_domain.py b/tests/api/test_custom_domain.py index 01c3ecf9..382f2039 100644 --- a/tests/api/test_custom_domain.py +++ b/tests/api/test_custom_domain.py @@ -1,5 +1,5 @@ from app.alias_utils import delete_alias -from app.models import CustomDomain, Alias +from app.models import CustomDomain, Alias, Mailbox from tests.utils import login @@ -34,6 +34,45 @@ def test_get_custom_domains(flask_client): assert "email" in mailbox +def test_update_custom_domains(flask_client): + user = login(flask_client) + + d1 = CustomDomain.create( + user_id=user.id, domain="test1.org", verified=True, commit=True + ) + + # test update catch all + assert d1.catch_all is False + r = flask_client.patch(f"/api/custom_domains/{d1.id}", json={"catch_all": True}) + assert r.status_code == 200 + assert d1.catch_all is True + + # test update random_prefix_generation + assert d1.random_prefix_generation is False + r = flask_client.patch( + f"/api/custom_domains/{d1.id}", json={"random_prefix_generation": True} + ) + assert r.status_code == 200 + assert d1.random_prefix_generation is True + + # test update name + assert d1.name is None + r = flask_client.patch(f"/api/custom_domains/{d1.id}", json={"name": "test name"}) + assert r.status_code == 200 + assert d1.name == "test name" + + # test update mailboxes + assert d1.mailboxes == [user.default_mailbox] + mb = Mailbox.create( + user_id=user.id, email="test@example.org", verified=True, commit=True + ) + r = flask_client.patch( + f"/api/custom_domains/{d1.id}", json={"mailbox_ids": [mb.id]} + ) + assert r.status_code == 200 + assert d1.mailboxes == [mb] + + def test_get_custom_domain_trash(flask_client): user = login(flask_client)