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
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" }
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
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
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"
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
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
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
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}
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
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
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
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
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"
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" )
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
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
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
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"
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
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
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
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
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"
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
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"]