From f87746e071d390495f7ab1431b132dbcc18cc15a Mon Sep 17 00:00:00 2001 From: Son NK Date: Sat, 14 Mar 2020 12:55:38 +0100 Subject: [PATCH] POST /api/aliases/:alias_id/contacts --- README.md | 25 +++++++++++++++ app/api/views/alias.py | 69 +++++++++++++++++++++++++++++++++++++++++ tests/api/test_alias.py | 36 +++++++++++++++++++++ 3 files changed, 130 insertions(+) diff --git a/README.md b/README.md index d335f8f4..4e28774f 100644 --- a/README.md +++ b/README.md @@ -950,6 +950,31 @@ If success, 200 with the list of contacts, for example: Please note that last_email_sent_timestamp and last_email_sent_date can be null. + +#### POST /api/aliases/:alias_id/contacts + +Create a new contact for an alias. + +Input: +- `Authentication` header that contains the api key +- `alias_id` in url. +- `contact` in request body + +Output: +If success, return 201 +Return 409 if contact is already added. + +``` +{ + "contact": "First Last ", + "creation_date": "2020-03-14 11:52:41+00:00", + "creation_timestamp": 1584186761, + "last_email_sent_date": null, + "last_email_sent_timestamp": null, + "reverse_alias": "First Last first@example.com " +} +``` + ### Database migration The database migration is handled by `alembic` diff --git a/app/api/views/alias.py b/app/api/views/alias.py index 7b753537..25f0dfdc 100644 --- a/app/api/views/alias.py +++ b/app/api/views/alias.py @@ -8,6 +8,21 @@ from app.dashboard.views.alias_log import get_alias_log from app.dashboard.views.index import get_alias_info, AliasInfo from app.extensions import db from app.models import GenEmail, ForwardEmail, ForwardEmailLog +from app.utils import random_string +import re + +from flask import render_template, request, redirect, url_for, flash +from flask_login import login_required, current_user +from flask_wtf import FlaskForm +from wtforms import StringField, validators, ValidationError + +from app.config import EMAIL_DOMAIN +from app.dashboard.base import dashboard_bp +from app.email_utils import get_email_part +from app.extensions import db +from app.log import LOG +from app.models import GenEmail, ForwardEmail +from app.utils import random_string @api_bp.route("/aliases") @@ -258,3 +273,57 @@ def get_alias_contacts_route(alias_id): contacts = get_alias_contacts(gen_email, page_id) return jsonify(contacts=contacts), 200 + + +@api_bp.route("/aliases//contacts", methods=["POST"]) +@cross_origin() +@verify_api_key +def create_contact_route(alias_id): + """ + Create contact for an alias + Input: + alias_id: in url + contact: in body + Output: + 201 if success + 409 if contact already added + + + """ + data = request.get_json() + if not data: + return jsonify(error="request body cannot be empty"), 400 + + user = g.user + gen_email: GenEmail = GenEmail.get(alias_id) + + if gen_email.user_id != user.id: + return jsonify(error="Forbidden"), 403 + + contact_email = data.get("contact") + + # generate a reply_email, make sure it is unique + # not use while to avoid infinite loop + reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}" + for _ in range(1000): + reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}" + if not ForwardEmail.get_by(reply_email=reply_email): + break + + website_email = get_email_part(contact_email) + + # already been added + if ForwardEmail.get_by(gen_email_id=gen_email.id, website_email=website_email): + return jsonify(error="Contact already added"), 409 + + forward_email = ForwardEmail.create( + gen_email_id=gen_email.id, + website_email=website_email, + website_from=contact_email, + reply_email=reply_email, + ) + + LOG.d("create reverse-alias for %s %s", contact_email, gen_email) + db.session.commit() + + return jsonify(**serialize_forward_email(forward_email)), 201 diff --git a/tests/api/test_alias.py b/tests/api/test_alias.py index 44c7e5ec..4a6aa67e 100644 --- a/tests/api/test_alias.py +++ b/tests/api/test_alias.py @@ -231,3 +231,39 @@ def test_alias_contacts(flask_client): headers={"Authentication": api_key.code}, ) assert len(r.json["contacts"]) == 1 + + +def test_create_contact_route(flask_client): + user = User.create( + email="a@b.c", password="password", name="Test User", activated=True + ) + db.session.commit() + + # create api_key + api_key = ApiKey.create(user.id, "for test") + db.session.commit() + + gen_email = GenEmail.create_new_random(user) + db.session.commit() + + r = flask_client.post( + url_for("api.create_contact_route", alias_id=gen_email.id), + headers={"Authentication": api_key.code}, + json={"contact": "First Last "}, + ) + + assert r.status_code == 201 + assert r.json["contact"] == "First Last " + assert "creation_date" in r.json + assert "creation_timestamp" in r.json + assert r.json["last_email_sent_date"] is None + assert r.json["last_email_sent_timestamp"] is None + assert r.json["reverse_alias"] + + # re-add a contact, should return 409 + r = flask_client.post( + url_for("api.create_contact_route", alias_id=gen_email.id), + headers={"Authentication": api_key.code}, + json={"contact": "First2 Last2 "}, + ) + assert r.status_code == 409