示例#1
0
def api_generate_apikey():
    data = request.get_json()
    description = None
    role_name = None
    apikey = None
    domain_obj_list = []

    abort(400) if 'domains' not in data else None
    abort(400) if not isinstance(data['domains'], (list, )) else None
    abort(400) if 'role' not in data else None

    description = data['description'] if 'description' in data else None
    role_name = data['role']
    domains = data['domains']

    if role_name == 'User' and len(domains) == 0:
        logging.error("Apikey with User role must have domains")
        raise ApiKeyNotUsable()
    elif role_name == 'User':
        domain_obj_list = Domain.query.filter(Domain.name.in_(domains)).all()
        if len(domain_obj_list) == 0:
            msg = "One of supplied domains does not exists"
            logging.error(msg)
            raise DomainNotExists(message=msg)

    if g.user.role.name not in ['Administrator', 'Operator']:
        # domain list of domain api key should be valid for
        # if not any domain error
        # role of api key, user cannot assign role above for api key
        if role_name != 'User':
            msg = "User cannot assign other role than User"
            logging.error(msg)
            raise NotEnoughPrivileges(message=msg)

        user_domain_obj_list = g.user.get_domains()

        domain_list = [item.name for item in domain_obj_list]
        user_domain_list = [item.name for item in user_domain_obj_list]

        logging.debug("Input domain list: {0}".format(domain_list))
        logging.debug("User domain list: {0}".format(user_domain_list))

        inter = set(domain_list).intersection(set(user_domain_list))

        if not (len(inter) == len(domain_list)):
            msg = "You don't have access to one of domains"
            logging.error(msg)
            raise DomainAccessForbidden(message=msg)

    apikey = ApiKey(desc=description,
                    role_name=role_name,
                    domains=domain_obj_list)

    try:
        apikey.create()
    except Exception as e:
        logging.error('Error: {0}'.format(e))
        raise ApiKeyCreateFail(message='Api key create failed')

    return json.dumps(apikey_plain_schema.dump([apikey])), 201
示例#2
0
def initial_apikey_data():
    pdns_proto = os.environ['PDNS_PROTO']
    pdns_host = os.environ['PDNS_HOST']
    pdns_port = os.environ['PDNS_PORT']
    pdns_api_url = '{0}://{1}:{2}'.format(pdns_proto, pdns_host, pdns_port)

    api_url_setting = Setting('pdns_api_url', pdns_api_url)
    api_key_setting = Setting('pdns_api_key', os.environ['PDNS_API_KEY'])
    allow_create_domain_setting = Setting('allow_user_create_domain', True)

    try:
        with app.app_context():
            flask_migrate.upgrade()

        db.session.add(api_url_setting)
        db.session.add(api_key_setting)
        db.session.add(allow_create_domain_setting)

        test_user_apikey = app.config.get('TEST_USER_APIKEY')
        test_admin_apikey = app.config.get('TEST_ADMIN_APIKEY')

        dummy_apikey = ApiKey(
            desc="dummy",
            role_name="Administrator"
        )

        admin_key = dummy_apikey.get_hashed_password(
            plain_text_password=test_admin_apikey
        ).decode('utf-8')

        admin_apikey = ApiKey(
            key=admin_key,
            desc="test admin apikey",
            role_name="Administrator"
        )
        admin_apikey.create()

        user_key = dummy_apikey.get_hashed_password(
            plain_text_password=test_user_apikey
        ).decode('utf-8')

        user_apikey = ApiKey(
            key=user_key,
            desc="test user apikey",
            role_name="User"
        )
        user_apikey.create()

    except Exception as e:
        logging.error("Unexpected ERROR: {0}".format(e))
        raise e

    yield

    db.session.close()
    os.unlink(app.config['TEST_DB_LOCATION'])
def test_out_of_quota(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create MAX_NB_EMAIL_FREE_PLAN custom alias to run out of quota
    for _ in range(MAX_NB_EMAIL_FREE_PLAN):
        GenEmail.create_new(user.id, prefix="test")

    word = random_word()
    r = flask_client.post(
        url_for("api.new_custom_alias", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
        json={
            "alias_prefix": "prefix",
            "alias_suffix": f".{word}@{EMAIL_DOMAIN}"
        },
    )

    assert r.status_code == 400
    assert r.json == {
        "error":
        "You have reached the limitation of a free account with the maximum of 3 aliases, please upgrade your plan to create more aliases"
    }
示例#4
0
def test_success_with_pagination(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create more aliases than PAGE_LIMIT
    for _ in range(PAGE_LIMIT + 1):
        GenEmail.create_new_random(user.id)
    db.session.commit()

    # get aliases on the 1st page, should return PAGE_LIMIT aliases
    r = flask_client.get(
        url_for("api.get_aliases", page_id=0),
        headers={"Authentication": api_key.code},
    )
    assert r.status_code == 200
    assert len(r.json["aliases"]) == PAGE_LIMIT

    # get aliases on the 2nd page, should return 2 aliases
    # as the total number of aliases is PAGE_LIMIT +2
    # 1 alias is created when user is created
    r = flask_client.get(
        url_for("api.get_aliases", page_id=1),
        headers={"Authentication": api_key.code},
    )
    assert r.status_code == 200
    assert len(r.json["aliases"]) == 2
示例#5
0
def test_get_mailboxes(flask_client):
    user = User.create(
        email="[email protected]", password="******", name="Test User", activated=True
    )
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    Mailbox.create(user_id=user.id, email="*****@*****.**", verified=True)
    Mailbox.create(user_id=user.id, email="*****@*****.**", verified=False)
    db.session.commit()

    r = flask_client.get(
        "/api/mailboxes",
        headers={"Authentication": api_key.code},
    )
    assert r.status_code == 200
    # [email protected] is not returned as it's not verified
    assert len(r.json["mailboxes"]) == 2

    for mb in r.json["mailboxes"]:
        assert "email" in mb
        assert "id" in mb
        assert "default" in mb
        assert "creation_timestamp" in mb
        assert "nb_alias" in mb
        assert "verified" in mb
示例#6
0
def test_out_of_quota(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create 3 custom alias to run out of quota
    GenEmail.create_new(user.id, prefix="test")
    GenEmail.create_new(user.id, prefix="test")
    GenEmail.create_new(user.id, prefix="test")

    r = flask_client.post(
        url_for("api.new_custom_alias", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
        json={
            "alias_prefix": "prefix",
            "alias_suffix": f".abcdef@{EMAIL_DOMAIN}"
        },
    )

    assert r.status_code == 400
    assert r.json == {
        "error":
        "You have created 3 custom aliases, please upgrade to create more"
    }
def test_success(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    r = flask_client.post(
        url_for("api.new_random_alias", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 201
    assert r.json["alias"].endswith(EMAIL_DOMAIN)

    # assert returned field
    res = r.json
    assert "id" in res
    assert "email" in res
    assert "creation_date" in res
    assert "creation_timestamp" in res
    assert "nb_forward" in res
    assert "nb_block" in res
    assert "nb_reply" in res
    assert "enabled" in res
    assert "note" in res
def test_custom_mode(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # without note
    r = flask_client.post(
        url_for("api.new_random_alias", hostname="www.test.com", mode="uuid"),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 201
    # extract the uuid part
    alias = r.json["alias"]
    uuid_part = alias[:len(alias) - len(EMAIL_DOMAIN) - 1]
    assert is_valid_uuid(uuid_part)

    # with note
    r = flask_client.post(
        url_for("api.new_random_alias", hostname="www.test.com", mode="uuid"),
        headers={"Authentication": api_key.code},
        json={"note": "test note"},
    )

    assert r.status_code == 201
    alias = r.json["alias"]
    ge = Alias.get_by(email=alias)
    assert ge.note == "test note"
示例#9
0
def test_create_contact_route(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    r = flask_client.post(
        url_for("api.create_contact_route", alias_id=alias.id),
        headers={"Authentication": api_key.code},
        json={"contact": "First Last <*****@*****.**>"},
    )

    assert r.status_code == 201
    assert r.json["contact"] == "*****@*****.**"
    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=alias.id),
        headers={"Authentication": api_key.code},
        json={"contact": "First2 Last2 <*****@*****.**>"},
    )
    assert r.status_code == 409
示例#10
0
def test_update_alias_mailboxes(flask_client):
    user = User.create(
        email="[email protected]", password="******", name="Test User", activated=True
    )
    db.session.commit()

    mb1 = Mailbox.create(user_id=user.id, email="*****@*****.**", verified=True)
    mb2 = Mailbox.create(user_id=user.id, email="*****@*****.**", verified=True)

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    r = flask_client.put(
        url_for("api.update_alias", alias_id=alias.id),
        headers={"Authentication": api_key.code},
        json={"mailbox_ids": [mb1.id, mb2.id]},
    )

    assert r.status_code == 200
    alias = Alias.get(alias.id)

    assert alias.mailbox
    assert len(alias._mailboxes) == 1

    # fail when update with empty mailboxes
    r = flask_client.put(
        url_for("api.update_alias", alias_id=alias.id),
        headers={"Authentication": api_key.code},
        json={"mailbox_ids": []},
    )
    assert r.status_code == 400
示例#11
0
def test_create_custom_alias_without_note(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create alias without note
    word = random_word()
    r = flask_client.post(
        url_for("api.new_custom_alias", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
        json={
            "alias_prefix": "prefix",
            "alias_suffix": f".{word}@{EMAIL_DOMAIN}"
        },
    )

    assert r.status_code == 201
    assert r.json["alias"] == f"prefix.{word}@{EMAIL_DOMAIN}"

    new_ge = Alias.get_by(email=r.json["alias"])
    assert new_ge.note is None
示例#12
0
def test_delete_contact(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    contact = Contact.create(
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        user_id=alias.user_id,
    )
    db.session.commit()

    r = flask_client.delete(
        url_for("api.delete_contact", contact_id=contact.id),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 200
    assert r.json == {"deleted": True}
示例#13
0
def test_get_alias(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create more aliases than PAGE_LIMIT
    alias = Alias.create_new_random(user)
    db.session.commit()

    # get aliases on the 1st page, should return PAGE_LIMIT aliases
    r = flask_client.get(
        url_for("api.get_alias", alias_id=alias.id),
        headers={"Authentication": api_key.code},
    )
    assert r.status_code == 200

    # assert returned field
    res = r.json
    assert "id" in res
    assert "email" in res
    assert "creation_date" in res
    assert "creation_timestamp" in res
    assert "nb_forward" in res
    assert "nb_block" in res
    assert "nb_reply" in res
    assert "enabled" in res
    assert "note" in res
示例#14
0
def test_get_aliases_with_pagination(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create more aliases than PAGE_LIMIT
    Alias.create_new(user, "prefix1")
    Alias.create_new(user, "prefix2")
    db.session.commit()

    # get aliases without query, should return 3 aliases as one alias is created when user is created
    r = flask_client.get(url_for("api.get_aliases", page_id=0),
                         headers={"Authentication": api_key.code})
    assert r.status_code == 200
    assert len(r.json["aliases"]) == 3

    # get aliases with "prefix1" query, should return 1 alias
    r = flask_client.get(
        url_for("api.get_aliases", page_id=0),
        headers={"Authentication": api_key.code},
        json={"query": "prefix1"},
    )
    assert r.status_code == 200
    assert len(r.json["aliases"]) == 1
示例#15
0
def test_set_mailbox_as_default(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create a mailbox
    mb = Mailbox.create(user_id=user.id, email="*****@*****.**")
    db.session.commit()
    assert user.default_mailbox_id != mb.id

    r = flask_client.put(
        url_for("api.delete_mailbox", mailbox_id=mb.id),
        headers={"Authentication": api_key.code},
        json={"default": True},
    )

    assert r.status_code == 200

    mb = Mailbox.get(mb.id)
    assert user.default_mailbox_id == mb.id
示例#16
0
def test_alias_activities(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    Session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    Session.commit()

    alias = Alias.create_new_random(user)
    Session.commit()

    # create some alias log
    contact = Contact.create(
        website_email="*****@*****.**",
        reply_email="[email protected]",
        alias_id=alias.id,
        user_id=alias.user_id,
    )
    Session.commit()

    for _ in range(int(PAGE_LIMIT / 2)):
        EmailLog.create(
            contact_id=contact.id,
            is_reply=True,
            user_id=contact.user_id,
            alias_id=contact.alias_id,
        )

    for _ in range(int(PAGE_LIMIT / 2) + 2):
        EmailLog.create(
            contact_id=contact.id,
            blocked=True,
            user_id=contact.user_id,
            alias_id=contact.alias_id,
        )

    r = flask_client.get(
        url_for("api.get_alias_activities", alias_id=alias.id, page_id=0),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 200
    assert len(r.json["activities"]) == PAGE_LIMIT
    for ac in r.json["activities"]:
        assert ac["from"]
        assert ac["to"]
        assert ac["timestamp"]
        assert ac["action"]
        assert ac["reverse_alias"]
        assert ac["reverse_alias_address"]

    # second page, should return 1 or 2 results only
    r = flask_client.get(
        url_for("api.get_alias_activities", alias_id=alias.id, page_id=1),
        headers={"Authentication": api_key.code},
    )
    assert len(r.json["activities"]) < 3
示例#17
0
def test_update_alias_name(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    r = flask_client.put(
        url_for("api.update_alias", alias_id=alias.id),
        headers={"Authentication": api_key.code},
        json={"name": "Test Name"},
    )
    assert r.status_code == 200
    alias = Alias.get(alias.id)
    assert alias.name == "Test Name"

    # update name with linebreak
    r = flask_client.put(
        url_for("api.update_alias", alias_id=alias.id),
        headers={"Authentication": api_key.code},
        json={"name": "Test \nName"},
    )
    assert r.status_code == 200
    alias = Alias.get(alias.id)
    assert alias.name == "Test Name"
示例#18
0
def test_update_alias_mailbox(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    mb = Mailbox.create(user_id=user.id, email="*****@*****.**", verified=True)

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    r = flask_client.put(
        url_for("api.update_alias", alias_id=alias.id),
        headers={"Authentication": api_key.code},
        json={"mailbox_id": mb.id},
    )

    assert r.status_code == 200

    # fail when update with non-existing mailbox
    r = flask_client.put(
        url_for("api.update_alias", alias_id=alias.id),
        headers={"Authentication": api_key.code},
        json={"mailbox_id": -1},
    )
    assert r.status_code == 400
def test_out_of_quota(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    user.trial_end = None
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create MAX_NB_EMAIL_FREE_PLAN random alias to run out of quota
    for _ in range(MAX_NB_EMAIL_FREE_PLAN):
        Alias.create_new(user, prefix="test1")

    r = flask_client.post(
        url_for("api.new_random_alias", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 400
    assert (
        r.json["error"] ==
        "You have reached the limitation of a free account with the maximum of 3 aliases, please upgrade your plan to create more aliases"
    )
示例#20
0
def test_cancel_mailbox_email_change(flask_client):
    user = User.create(
        email="[email protected]", password="******", name="Test User", activated=True
    )
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create a mailbox
    mb = Mailbox.create(user_id=user.id, email="*****@*****.**")
    db.session.commit()

    # update mailbox email
    r = flask_client.put(
        f"/api/mailboxes/{mb.id}",
        headers={"Authentication": api_key.code},
        json={"email": "*****@*****.**"},
    )
    assert r.status_code == 200

    mb = Mailbox.get(mb.id)
    assert mb.new_email == "*****@*****.**"

    # cancel mailbox email change
    r = flask_client.put(
        url_for("api.delete_mailbox", mailbox_id=mb.id),
        headers={"Authentication": api_key.code},
        json={"cancel_email_change": True},
    )
    assert r.status_code == 200

    mb = Mailbox.get(mb.id)
    assert mb.new_email is None
示例#21
0
def auth_mfa():
    """
    Validate the OTP Token
    Input:
        mfa_token: OTP token that user enters
        mfa_key: MFA key obtained in previous auth request, e.g. /api/auth/login
        device: the device name, used to create an ApiKey associated with this device
    Output:
        200 and user info containing:
        {
            name: "John Wick",
            api_key: "a long string",
            email: "user email"
        }

    """
    data = request.get_json()
    if not data:
        return jsonify(error="request body cannot be empty"), 400

    mfa_token = data.get("mfa_token")
    mfa_key = data.get("mfa_key")
    device = data.get("device")

    s = Signer(FLASK_SECRET)
    try:
        user_id = int(s.unsign(mfa_key))
    except Exception:
        return jsonify(error="Invalid mfa_key"), 400

    user = User.get(user_id)

    if not user:
        return jsonify(error="Invalid mfa_key"), 400
    elif not user.enable_otp:
        return (
            jsonify(
                error=
                "This endpoint should only be used by user who enables MFA"),
            400,
        )

    totp = pyotp.TOTP(user.otp_secret)
    if not totp.verify(mfa_token):
        return jsonify(error="Wrong TOTP Token"), 400

    ret = {"name": user.name or "", "email": user.email}

    api_key = ApiKey.get_by(user_id=user.id, name=device)
    if not api_key:
        LOG.d("create new api key for %s and %s", user, device)
        api_key = ApiKey.create(user.id, device)
        db.session.commit()

    ret["api_key"] = api_key.code

    # so user is logged in automatically on the web
    login_user(user)

    return jsonify(**ret), 200
示例#22
0
def auth_payload(user, device) -> dict:
    ret = {
        "name": user.name or "",
        "email": user.email,
        "mfa_enabled": user.enable_otp
    }

    # do not give api_key, user can only obtain api_key after OTP verification
    if user.enable_otp:
        s = Signer(FLASK_SECRET)
        ret["mfa_key"] = s.sign(str(user.id))
        ret["api_key"] = None
    else:
        api_key = ApiKey.get_by(user_id=user.id, name=device)
        if not api_key:
            LOG.d("create new api key for %s and %s", user, device)
            api_key = ApiKey.create(user.id, device)
            db.session.commit()
        ret["mfa_key"] = None
        ret["api_key"] = api_key.code

        # so user is automatically logged in on the web
        login_user(user)

    return ret
示例#23
0
def test_different_scenarios_v5(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    Session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    Session.commit()

    # <<< without hostname >>>
    r = flask_client.get("/api/v5/alias/options",
                         headers={"Authentication": api_key.code})

    assert r.status_code == 200

    assert r.json["can_create"]
    assert r.json["suffixes"]
    assert r.json["prefix_suggestion"] == ""  # no hostname => no suggestion

    for suffix_payload in r.json["suffixes"]:
        suffix, signed_suffix = (
            suffix_payload["suffix"],
            suffix_payload["signed_suffix"],
        )
        assert signed_suffix.startswith(suffix)

    # <<< with hostname >>>
    r = flask_client.get(
        "/api/v5/alias/options?hostname=www.test.com",
        headers={"Authentication": api_key.code},
    )
    assert r.json["prefix_suggestion"] == "test"

    # <<< with hostname with 2 parts TLD, for example wwww.numberoneshoes.co.nz >>>
    r = flask_client.get(
        "/api/v5/alias/options?hostname=wwww.numberoneshoes.co.nz",
        headers={"Authentication": api_key.code},
    )
    assert r.json["prefix_suggestion"] == "numberoneshoes"

    # <<< with recommendation >>>
    alias = Alias.create_new(user, prefix="test")
    Session.commit()
    AliasUsedOn.create(alias_id=alias.id,
                       hostname="www.test.com",
                       user_id=alias.user_id)
    Session.commit()

    r = flask_client.get(
        url_for("api.options_v4", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
    )
    assert r.json["recommendation"]["alias"] == alias.email
    assert r.json["recommendation"]["hostname"] == "www.test.com"
示例#24
0
def test_success_v3(flask_client):
    user = User.create(
        email="[email protected]",
        password="******",
        name="Test User",
        activated=True,
    )
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create another mailbox
    mb = Mailbox.create(user_id=user.id, email="*****@*****.**", verified=True)
    db.session.commit()

    # create new alias with note
    word = random_word()
    suffix = f".{word}@{EMAIL_DOMAIN}"
    suffix = signer.sign(suffix).decode()

    r = flask_client.post(
        url_for("api.new_custom_alias_v3", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
        json={
            "alias_prefix": "prefix",
            "signed_suffix": suffix,
            "note": "test note",
            "mailbox_ids": [user.default_mailbox_id, mb.id],
            "name": "your name",
        },
    )

    assert r.status_code == 201
    assert r.json["alias"] == f"prefix.{word}@{EMAIL_DOMAIN}"

    # assert returned field
    res = r.json
    assert "id" in res
    assert "email" in res
    assert "creation_date" in res
    assert "creation_timestamp" in res
    assert "nb_forward" in res
    assert "nb_block" in res
    assert "nb_reply" in res
    assert "enabled" in res
    assert "note" in res
    assert res["name"] == "your name"

    new_alias: Alias = Alias.get_by(email=r.json["alias"])
    assert new_alias.note == "test note"
    assert len(new_alias.mailboxes) == 2
示例#25
0
def test_alias_contacts(flask_client):
    user = User.create(
        email="[email protected]", password="******", name="Test User", activated=True
    )
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    # create some alias log
    for i in range(PAGE_LIMIT + 1):
        contact = Contact.create(
            website_email=f"marketing-{i}@example.com",
            reply_email=f"reply-{i}@a.b",
            alias_id=alias.id,
            user_id=alias.user_id,
        )
        db.session.commit()

        EmailLog.create(
            contact_id=contact.id,
            is_reply=True,
            user_id=contact.user_id,
            alias_id=contact.alias_id,
        )
        db.session.commit()

    r = flask_client.get(
        url_for("api.get_alias_contacts_route", alias_id=alias.id, page_id=0),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 200
    assert len(r.json["contacts"]) == PAGE_LIMIT
    for ac in r.json["contacts"]:
        assert ac["creation_date"]
        assert ac["creation_timestamp"]
        assert ac["last_email_sent_date"]
        assert ac["last_email_sent_timestamp"]
        assert ac["contact"]
        assert ac["reverse_alias"]
        assert ac["reverse_alias_address"]

    # second page, should return 1 result only
    r = flask_client.get(
        url_for("api.get_alias_contacts_route", alias_id=alias.id, page_id=1),
        headers={"Authentication": api_key.code},
    )
    assert len(r.json["contacts"]) == 1
示例#26
0
def test_delete_all_api_keys(flask_client):
    # create two test users
    user_1 = login(flask_client)
    user_2 = User.create(email="[email protected]",
                         password="******",
                         name="Test User 2",
                         activated=True)
    Session.commit()

    # create api_key for both users
    ApiKey.create(user_1.id, "for test")
    ApiKey.create(user_1.id, "for test 2")
    ApiKey.create(user_2.id, "for test")
    Session.commit()

    assert (ApiKey.count() == 3
            )  # assert that the total number of API keys for all users is 3.
    # assert that each user has the API keys created
    assert ApiKey.filter(ApiKey.user_id == user_1.id).count() == 2
    assert ApiKey.filter(ApiKey.user_id == user_2.id).count() == 1

    # delete all of user 1's API keys
    r = flask_client.post(
        url_for("dashboard.api_key"),
        data={"form-name": "delete-all"},
        follow_redirects=True,
    )
    assert r.status_code == 200
    assert (
        ApiKey.count() == 1
    )  # assert that the total number of API keys for all users is now 1.
    assert (ApiKey.filter(ApiKey.user_id == user_1.id).count() == 0
            )  # assert that user 1 now has 0 API keys
    assert (ApiKey.filter(ApiKey.user_id == user_2.id).count() == 1
            )  # assert that user 2 still has 1 API key
示例#27
0
def auth_login():
    """
    Authenticate user
    Input:
        email
        password
        device: to create an ApiKey associated with this device
    Output:
        200 and user info containing:
        {
            name: "John Wick",
            mfa_enabled: true,
            mfa_key: "a long string",
            api_key: "a long string"
        }

    """
    data = request.get_json()
    if not data:
        return jsonify(error="request body cannot be empty"), 400

    email = data.get("email")
    password = data.get("password")
    device = data.get("device")

    user = User.filter_by(email=email).first()

    if not user or not user.check_password(password):
        return jsonify(error="Email or password incorrect"), 400
    elif not user.activated:
        return jsonify(error="Account not activated"), 400

    ret = {
        "name": user.name,
        "mfa_enabled": user.enable_otp,
    }

    # do not give api_key, user can only obtain api_key after OTP verification
    if user.enable_otp:
        s = Signer(FLASK_SECRET)
        ret["mfa_key"] = s.sign(str(user.id))
        ret["api_key"] = None
    else:
        api_key = ApiKey.get_by(user_id=user.id, name=device)
        if not api_key:
            LOG.d("create new api key for %s and %s", user, device)
            api_key = ApiKey.create(user.id, device)
            db.session.commit()
        ret["mfa_key"] = None
        ret["api_key"] = api_key.code

    return jsonify(**ret), 200
示例#28
0
def test_different_scenarios(flask_client):
    user = User.create(
        email="[email protected]",
        password="******",
        name="Test User",
        activated=True,
        commit=True,
    )

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # <<< without hostname >>>
    r = flask_client.get(url_for("api.options"),
                         headers={"Authentication": api_key.code})

    # {
    #     "can_create_custom": True,
    #     "custom": {"suffixes": ["*****@*****.**"], "suggestion": ""},
    #     "existing": ["*****@*****.**"],
    # }
    assert r.status_code == 200
    assert r.json["can_create_custom"]
    assert len(r.json["existing"]) == 1
    assert len(r.json["custom"]["suffixes"]) == 4

    assert r.json["custom"]["suggestion"] == ""  # no hostname => no suggestion

    # <<< with hostname >>>
    r = flask_client.get(
        url_for("api.options", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
    )

    assert r.json["custom"]["suggestion"] == "test"

    # <<< with recommendation >>>
    alias = Alias.create_new(user, prefix="test")
    db.session.commit()
    AliasUsedOn.create(alias_id=alias.id,
                       hostname="www.test.com",
                       user_id=user.id)
    db.session.commit()

    r = flask_client.get(
        url_for("api.options", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
    )
    assert r.json["recommendation"]["alias"] == alias.email
    assert r.json["recommendation"]["hostname"] == "www.test.com"
示例#29
0
def test_cannot_create_alias_in_trash(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    # create a custom domain
    CustomDomain.create(user_id=user.id, domain="ab.cd", verified=True)
    db.session.commit()

    # create new alias with note
    suffix = "@ab.cd"
    suffix = signer.sign(suffix).decode()

    r = flask_client.post(
        url_for("api.new_custom_alias_v2", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
        json={
            "alias_prefix": "prefix",
            "signed_suffix": suffix,
            "note": "test note",
        },
    )

    # assert alias creation is successful
    assert r.status_code == 201
    assert r.json["alias"] == "*****@*****.**"

    # delete alias: it's going to be moved to ab.cd trash
    alias = Alias.get_by(email="*****@*****.**")
    assert alias.custom_domain_id
    delete_alias(alias, user)

    # try to create the same alias, will fail as the alias is in trash
    r = flask_client.post(
        url_for("api.new_custom_alias_v2", hostname="www.test.com"),
        headers={"Authentication": api_key.code},
        json={
            "alias_prefix": "prefix",
            "signed_suffix": suffix,
            "note": "test note",
        },
    )
    assert r.status_code == 409
示例#30
0
def test_get_aliases_error_without_pagination(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    r = flask_client.get(url_for("api.get_aliases"),
                         headers={"Authentication": api_key.code})

    assert r.status_code == 400
    assert r.json["error"]