From 0a121093426e85707dc234d6fafc240d8cb603c5 Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 28 May 2018 14:21:50 -0600 Subject: [PATCH 1/9] config values --- config/default.py | 5 +++++ config/development.py | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/config/default.py b/config/default.py index 9c012dc..5b18b84 100644 --- a/config/default.py +++ b/config/default.py @@ -22,3 +22,8 @@ PA_SSH_URL = 'url' PA_SSH_REMOTE_BIND_ADDR = 'addr' PA_SSH_REMOTE_BIND_PORT = 'port' + + +BACK_JWT_TOKEN = '' +OC_URL = '' +DEV_GITHUB_REPO_PATH = '' diff --git a/config/development.py b/config/development.py index 1b3062d..0bd2354 100644 --- a/config/development.py +++ b/config/development.py @@ -26,3 +26,7 @@ RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') GITHUB_JWT = config('GITHUB_JWT') GITHUB_REPO_PATH = config('DEV_GITHUB_REPO_PATH') + +BACK_JWT_TOKEN = config('BACK_JWT_TOKEN') +OC_URL = config('OC_URL') +DEV_GITHUB_REPO_PATH = '' \ No newline at end of file From 0de623273be627aab7f67240bb3051fe8df716b0 Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 28 May 2018 14:23:12 -0600 Subject: [PATCH 2/9] initial health check for jwt --- ocbot/external/route_backend.py | 59 +++++++++++++++++++ tests/external_tests/test_route_backend.py | 48 +++++++++++++++ .../external_tests/test_route_backend_data.py | 20 +++++++ 3 files changed, 127 insertions(+) create mode 100644 ocbot/external/route_backend.py create mode 100644 tests/external_tests/test_route_backend.py create mode 100644 tests/external_tests/test_route_backend_data.py diff --git a/ocbot/external/route_backend.py b/ocbot/external/route_backend.py new file mode 100644 index 0000000..2cd0d9a --- /dev/null +++ b/ocbot/external/route_backend.py @@ -0,0 +1,59 @@ +import logging + +from requests import get as req_get + +from config.configs import configs + +logger = logging.getLogger(__name__) +JWT_BACKEND_TOKEN = configs['BACK_JWT_TOKEN'] +OC_BACKEND_URL = configs['OC_URL'] + + +class OCBackend: + # Store the instance + + _back_suffix = 'api/v1/slack_users' + _bearer_token = '' + + def __init__(self, *, jwt_token=None): + self._verification_token = jwt_token or JWT_BACKEND_TOKEN + self._bearer_token = f'Bearer {self._verification_token}' + + def build_url(self, route_string): + return f'{OC_BACKEND_URL}/{self._back_suffix}/{route_string}' + + def check_health(self): + route_url = self.build_url('access') + + response = req_get(route_url, headers={"Authorization": self._bearer_token}) + + if not response.ok: + val = response.json() + raise OCException(response.json()['errors'][0], response.status_code) + + return True + + +class OCException(Exception): + def __init__(selfself, message, status_code): + bad_response_dict = {'Invalid auth token': ExpiredTokenException, + 'Auth token has expired': InvalidTokenException, + 'Auth token is invalid': UndecodableTokenException, + } + + raise bad_response_dict[message]() + + +class ExpiredTokenException(OCException): + def __init__(self): + self.message = 'Expired Auth Token' + + +class InvalidTokenException(OCException): + def __init__(self): + self.message = 'Incorrect JWT token sent' + + +class UndecodableTokenException(OCException): + def __init__(self): + self.message = 'Server Couldn\'t decode token' diff --git a/tests/external_tests/test_route_backend.py b/tests/external_tests/test_route_backend.py new file mode 100644 index 0000000..3444f5a --- /dev/null +++ b/tests/external_tests/test_route_backend.py @@ -0,0 +1,48 @@ +import logging + +import pytest + + +from config.configs import configs +from ocbot.external.route_backend import OCBackend, ExpiredTokenException, InvalidTokenException, UndecodableTokenException + +from tests.external_tests.test_route_backend_data import * +logger = logging.getLogger(__name__) + +CORRECT_TOKEN = configs['BACK_JWT_TOKEN'] +# NOT A REAL TOKEN DONT TRY BITCHES +BAD_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJzb21lIHJhbmRvbSBrZXkiLCJleHAiOjE4ODc1MjQ5Mzh9.cKikBK-AkMoIyAopLh1JjYi9cKyorkYE9FCX5LQHLy8' +SHORT_TOKEN = 'a' + + +# Good Health Check +def test_good_health(): + """ + Asserts build_message function correctly formats message. + """ + client = OCBackend(jwt_token=CORRECT_TOKEN) + resp = client.check_health() + assert resp == True + # assert resp.payload.message == good_health['payload']['message'] + # assert resp == good_health + + +def test_invalid_token(mocker): + mocker.patch('ocbot.external.route_backend.OCBackend.req_get.response.json', return_value=incorrect_token) + client = OCBackend(jwt_token=BAD_TOKEN) + with pytest.raises(InvalidTokenException) as e_info: + resp = client.check_health() + + +def test_expired_token(mocker): + mocker.patch('ocbot.external.route_backend.OCBackend.req_get.response.json', return_value=expired_token) + client = OCBackend(jwt_token=BAD_TOKEN) + with pytest.raises(ExpiredTokenException) as e_info: + resp = client.check_health() + + +def test_nondecodable_token(mocker): + mocker.patch('ocbot.external.route_backend.OCBackend.req_get.response.json', return_value=non_decodeable_token) + client = OCBackend(jwt_token=SHORT_TOKEN) + with pytest.raises(UndecodableTokenException) as e_info: + resp = client.check_health() diff --git a/tests/external_tests/test_route_backend_data.py b/tests/external_tests/test_route_backend_data.py new file mode 100644 index 0000000..16728ac --- /dev/null +++ b/tests/external_tests/test_route_backend_data.py @@ -0,0 +1,20 @@ +incorrect_token = { + "errors": [ + "Auth token is invalid" + ] + +} + +expired_token = { + "errors": [ + "Auth token has expired" + ] + +} + +non_decodeable_token = { + "errors": [ + "Invalid auth token" + ] + +} From 169b75a876da23a43fc71be44a20548ff594898b Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 28 May 2018 16:19:23 -0600 Subject: [PATCH 3/9] Fixed test cases and configs. --- config/tests.py | 6 +++- ocbot/external/route_backend.py | 13 +++++---- tests/external_tests/test_route_backend.py | 28 +++++++++++++++---- .../external_tests/test_route_backend_data.py | 6 ++-- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/config/tests.py b/config/tests.py index c8ec4fa..55c2d6d 100644 --- a/config/tests.py +++ b/config/tests.py @@ -25,4 +25,8 @@ RECAPTCHA_SECRET = 'secret' GITHUB_JWT = 'jwt' -GITHUB_REPO_PATH = config('DEV_GITHUB_REPO_PATH') \ No newline at end of file +GITHUB_REPO_PATH = config('DEV_GITHUB_REPO_PATH') + +BACK_JWT_TOKEN = config('BACK_JWT_TOKEN') +OC_URL = config('OC_URL') +DEV_GITHUB_REPO_PATH = '' \ No newline at end of file diff --git a/ocbot/external/route_backend.py b/ocbot/external/route_backend.py index 2cd0d9a..a1da71c 100644 --- a/ocbot/external/route_backend.py +++ b/ocbot/external/route_backend.py @@ -1,6 +1,6 @@ import logging -from requests import get as req_get +import requests from config.configs import configs @@ -25,7 +25,7 @@ def build_url(self, route_string): def check_health(self): route_url = self.build_url('access') - response = req_get(route_url, headers={"Authorization": self._bearer_token}) + response = self.do_get(route_url) if not response.ok: val = response.json() @@ -33,12 +33,15 @@ def check_health(self): return True + def do_get(self, route_url): + return requests.get(route_url, headers={"Authorization": self._bearer_token}) + class OCException(Exception): def __init__(selfself, message, status_code): - bad_response_dict = {'Invalid auth token': ExpiredTokenException, - 'Auth token has expired': InvalidTokenException, - 'Auth token is invalid': UndecodableTokenException, + bad_response_dict = {'Invalid auth token': UndecodableTokenException, + 'Auth token has expired': ExpiredTokenException, + 'Auth token is invalid': InvalidTokenException, } raise bad_response_dict[message]() diff --git a/tests/external_tests/test_route_backend.py b/tests/external_tests/test_route_backend.py index 3444f5a..7e75ded 100644 --- a/tests/external_tests/test_route_backend.py +++ b/tests/external_tests/test_route_backend.py @@ -1,12 +1,13 @@ import logging import pytest - +import pytest_mock from config.configs import configs -from ocbot.external.route_backend import OCBackend, ExpiredTokenException, InvalidTokenException, UndecodableTokenException - +from ocbot.external.route_backend import OCBackend, ExpiredTokenException, InvalidTokenException, \ + UndecodableTokenException from tests.external_tests.test_route_backend_data import * + logger = logging.getLogger(__name__) CORRECT_TOKEN = configs['BACK_JWT_TOKEN'] @@ -28,21 +29,36 @@ def test_good_health(): def test_invalid_token(mocker): - mocker.patch('ocbot.external.route_backend.OCBackend.req_get.response.json', return_value=incorrect_token) + mock = mocker.Mock + mock.ok = False + mock.json = lambda: invalid_token + mock.status_code = 400 + mocker.patch('requests.get', return_value=mock) client = OCBackend(jwt_token=BAD_TOKEN) with pytest.raises(InvalidTokenException) as e_info: resp = client.check_health() + + def test_expired_token(mocker): - mocker.patch('ocbot.external.route_backend.OCBackend.req_get.response.json', return_value=expired_token) + mock = mocker.Mock + mock.ok = False + mock.json = lambda: expired_token + mock.status_code = 400 + mocker.patch('requests.get', return_value=mock) client = OCBackend(jwt_token=BAD_TOKEN) with pytest.raises(ExpiredTokenException) as e_info: resp = client.check_health() + def test_nondecodable_token(mocker): - mocker.patch('ocbot.external.route_backend.OCBackend.req_get.response.json', return_value=non_decodeable_token) + mock = mocker.Mock + mock.ok = False + mock.json = lambda: non_decodeable_token + mock.status_code = 400 + mocker.patch('requests.get', return_value=mock) client = OCBackend(jwt_token=SHORT_TOKEN) with pytest.raises(UndecodableTokenException) as e_info: resp = client.check_health() diff --git a/tests/external_tests/test_route_backend_data.py b/tests/external_tests/test_route_backend_data.py index 16728ac..660a0bd 100644 --- a/tests/external_tests/test_route_backend_data.py +++ b/tests/external_tests/test_route_backend_data.py @@ -1,20 +1,18 @@ -incorrect_token = { +invalid_token = { "errors": [ "Auth token is invalid" ] - } expired_token = { "errors": [ "Auth token has expired" ] - } non_decodeable_token = { "errors": [ + "Invalid auth token" ] - } From 11187b36851237a1dc3dda3b1aa4c71831240e7b Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 28 May 2018 18:40:17 -0600 Subject: [PATCH 4/9] Updated config files for each system to match syntax, be more declarative and removed mention of pythonanywhere --- config/{configs.py => all_config_loader.py} | 0 config/awsDev.py | 18 +++++-- config/awsProd.py | 18 ++++--- config/default.py | 53 +++++++++---------- config/development.py | 22 ++++---- config/development2.py | 20 +++---- config/production.py | 16 +++--- config/tests.py | 20 +++---- ocbot/__init__.py | 2 +- ocbot/external/route_airtable.py | 2 +- ocbot/external/route_backend.py | 6 +-- ocbot/external/route_slack.py | 6 +-- .../handlers/airtable_request_handler.py | 4 +- ocbot/pipeline/handlers/newmember.py | 4 +- ocbot/pipeline/handlers/suggestion.py | 4 +- .../web_api_handlers/handle_code_school.py | 2 +- ocbot/web/routes_slack.py | 4 +- ocbot/web/routes_web.py | 4 +- tests/external_tests/test_route_backend.py | 4 +- tests/handler_tests/test_airtable_request.py | 4 +- tests/test_flask.py | 4 +- 21 files changed, 114 insertions(+), 103 deletions(-) rename config/{configs.py => all_config_loader.py} (100%) diff --git a/config/configs.py b/config/all_config_loader.py similarity index 100% rename from config/configs.py rename to config/all_config_loader.py diff --git a/config/awsDev.py b/config/awsDev.py index ef9461a..263e316 100644 --- a/config/awsDev.py +++ b/config/awsDev.py @@ -1,11 +1,13 @@ from decouple import config +DEBUG = True + PORT = 5000 -TOKEN = config('DEV_BOT_TOKEN', default='token') -VERIFICATION_TOKEN = config('DEV_AUTH_TOKEN', default='token') -COMMUNITY_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='community_channel') -MENTORS_INTERNAL_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='mentor_channel') +SLACK_TOKEN = config('DEV_BOT_TOKEN', default='token') +SLACK_VERIFICATION_TOKEN = config('DEV_AUTH_TOKEN', default='token') +SLACK_COMMUNITY_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='community_channel') +SLACK_MENTORS_INTERNAL_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='mentor_channel') AIRTABLE_BASE_KEY = config('DEV_AIRTABLE_BASE_KEY', default='fake_airtable_base') AIRTABLE_API_KEY = config('DEV_AIRTABLE_TOKEN', default='fake_airtable_key') @@ -16,3 +18,11 @@ DB_DIALECT = config('AWS_DEV_DB_DIALECT', default='sqlite') DB_ADDR = config('AWS_DEV_DB_ADDR', default='dev.db') DB_NAME = config('AWS_DEV_DB_NAME', default='') + +GOOGLE_RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') + +GITHUB_JWT = config('GITHUB_JWT') +GITHUB_REPO_PATH = config('GITHUB_REPO_PATH') + +OC_BACKEND_JWT_TOKEN = config('OC_BACKEND_JWT_TOKEN') +OC_BACKEND_URL = config('OC_BACKEND_URL') diff --git a/config/awsProd.py b/config/awsProd.py index 5a2c2d4..6e93087 100644 --- a/config/awsProd.py +++ b/config/awsProd.py @@ -2,10 +2,12 @@ DEBUG = False -TOKEN = config('PROD_BOT_TOKEN') -VERIFICATION_TOKEN = config('PROD_AUTH_TOKEN') -COMMUNITY_CHANNEL = config('PROD_COMMUNITY_CHANNEL') -MENTORS_INTERNAL_CHANNEL = config('PROD_MENTOR_CHANNEL') +#PORT = 5000 + +SLACK_TOKEN = config('PROD_BOT_TOKEN') +SLACK_VERIFICATION_TOKEN = config('PROD_AUTH_TOKEN') +SLACK_COMMUNITY_CHANNEL = config('PROD_COMMUNITY_CHANNEL') +SLACK_MENTORS_INTERNAL_CHANNEL = config('PROD_MENTOR_CHANNEL') AIRTABLE_BASE_KEY = config('PROD_AIRTABLE_BASE_KEY') AIRTABLE_API_KEY = config('PROD_AIRTABLE_TOKEN') @@ -17,6 +19,10 @@ DB_ADDR = config('PROD_DB_ADDR', default='dev.db') DB_NAME = config('PROD_DB_NAME', default='') -RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') +GOOGLE_RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') + GITHUB_JWT = config('GITHUB_JWT') -GITHUB_REPO_PATH = config('GITHUB_REPO_PATH') \ No newline at end of file +GITHUB_REPO_PATH = config('GITHUB_REPO_PATH') + +OC_BACKEND_JWT_TOKEN = config('OC_BACKEND_JWT_TOKEN') +OC_BACKEND_URL = config('OC_BACKEND_URL') diff --git a/config/default.py b/config/default.py index 5b18b84..91247ee 100644 --- a/config/default.py +++ b/config/default.py @@ -1,29 +1,28 @@ + + DEBUG = True -VERIFICATION_TOKEN = 'token' -TOKEN = 'token' -COMMUNITY_CHANNEL = 'community_channel' -MENTORS_INTERNAL_CHANNEL = 'mentor_channel' - -AIRTABLE_BASE_KEY = 'fake_airtable_base' -AIRTABLE_API_KEY = 'fake_airtable_key' -AIRTABLE_TABLE_NAME = 'Mentor Request' - -# database stuff -DB_USERNAME = '' -DB_PASSWORD = '' -DB_DIALECT = 'sqlite' -DB_ADDR = 'dev.db' -DB_NAME = '' - -# PythonAnywhere SSH Tunnel Configurations -PA_SSH_USERNAME = 'username' -PA_SSH_PASSWORD = 'password' -PA_SSH_URL = 'url' -PA_SSH_REMOTE_BIND_ADDR = 'addr' -PA_SSH_REMOTE_BIND_PORT = 'port' - - -BACK_JWT_TOKEN = '' -OC_URL = '' -DEV_GITHUB_REPO_PATH = '' +PORT = 5000 + +SLACK_VERIFICATION_TOKEN = 'default_verification_token' +SLACK_TOKEN = 'default_token' +SLACK_COMMUNITY_CHANNEL = 'default_community_channel' +SLACK_MENTORS_INTERNAL_CHANNEL = 'default_mentor_channel' + +AIRTABLE_BASE_KEY = 'default_fake_airtable_base' +AIRTABLE_API_KEY = 'default_fake_airtable_key' +AIRTABLE_TABLE_NAME = 'default Mentor Request' + +DB_USERNAME = 'default_db_username' +DB_PASSWORD = 'default_db_password' +DB_DIALECT = 'defaultsqlite_dialect' +DB_ADDR = 'default_dev.db' +DB_NAME = 'default_db_name' + +RECAPTCHA_SECRET = 'default' + +GITHUB_JWT = 'default' +GITHUB_REPO_PATH = 'default' + +OC_BACKEND_JWT_TOKEN = 'default_jwt_token' +OC_BACKEND_URL = 'default_oc_url' diff --git a/config/development.py b/config/development.py index 0bd2354..d4a518d 100644 --- a/config/development.py +++ b/config/development.py @@ -1,11 +1,13 @@ from decouple import config +DEBUG = True + PORT = 5000 -TOKEN = config('DEV_BOT_TOKEN', default='token') -VERIFICATION_TOKEN = config('DEV_AUTH_TOKEN', default='token') -COMMUNITY_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='community_channel') -MENTORS_INTERNAL_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='mentor_channel') +SLACK_TOKEN = config('DEV_BOT_TOKEN', default='token') +SLACK_VERIFICATION_TOKEN = config('DEV_AUTH_TOKEN', default='token') +SLACK_COMMUNITY_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='community_channel') +SLACK_MENTORS_INTERNAL_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='mentor_channel') AIRTABLE_BASE_KEY = config('DEV_AIRTABLE_BASE_KEY', default='fake_airtable_base') AIRTABLE_API_KEY = config('DEV_AIRTABLE_TOKEN', default='fake_airtable_key') @@ -17,16 +19,10 @@ DB_ADDR = config('DEV_DB_ADDR', default='dev.db') DB_NAME = config('DEV_DB_NAME', default='') -PA_SSH_USERNAME = config('PA_SSH_USERNAME', default=None) -PA_SSH_PASSWORD = config('PA_SSH_PASSWORD', default=None) -PA_SSH_URL = config('PA_SSH_URL', default=None) -PA_SSH_REMOTE_BIND_ADDR = config('PA_PG_IP_ADDR', cast=str, default=None) -PA_SSH_REMOTE_BIND_PORT = config('PA_PG_PORT', cast=int, default=0) +GOOGLE_RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') -RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') GITHUB_JWT = config('GITHUB_JWT') GITHUB_REPO_PATH = config('DEV_GITHUB_REPO_PATH') -BACK_JWT_TOKEN = config('BACK_JWT_TOKEN') -OC_URL = config('OC_URL') -DEV_GITHUB_REPO_PATH = '' \ No newline at end of file +OC_BACKEND_JWT_TOKEN = config('OC_BACKEND_JWT_TOKEN') +OC_BACKEND_URL = config('OC_BACKEND_URL') diff --git a/config/development2.py b/config/development2.py index bb5bd8a..4a21153 100644 --- a/config/development2.py +++ b/config/development2.py @@ -2,10 +2,10 @@ PORT = 5000 -TOKEN = config('PERSONAL_BOT_TOKEN', default='token') -VERIFICATION_TOKEN = config('APP_VERIFICATION_TOKEN', default='token') -COMMUNITY_CHANNEL = config('PERSONAL_PRIVATE_CHANNEL', default='community_channel') -MENTORS_INTERNAL_CHANNEL = config('PERSONAL_PRIVATE_CHANNEL', default='mentor_channel') +SLACK_TOKEN = config('PERSONAL_BOT_TOKEN', default='token') +SLACK_VERIFICATION_TOKEN = config('APP_VERIFICATION_TOKEN', default='token') +SLACK_COMMUNITY_CHANNEL = config('PERSONAL_PRIVATE_CHANNEL', default='community_channel') +SLACK_MENTORS_INTERNAL_CHANNEL = config('PERSONAL_PRIVATE_CHANNEL', default='mentor_channel') AIRTABLE_BASE_KEY = config('DEV_AIRTABLE_BASE_KEY', default='fake_airtable_base') AIRTABLE_API_KEY = config('DEV_AIRTABLE_TOKEN', default='fake_airtable_key') @@ -17,8 +17,10 @@ DB_ADDR = config('DEV_DB_ADDR', default='dev.db') DB_NAME = config('DEV_DB_NAME', default='') -PA_SSH_USERNAME = config('PA_SSH_USERNAME', default=None) -PA_SSH_PASSWORD = config('PA_SSH_PASSWORD', default=None) -PA_SSH_URL = config('PA_SSH_URL', default=None) -PA_SSH_REMOTE_BIND_ADDR = config('PA_PG_IP_ADDR', cast=str, default=None) -PA_SSH_REMOTE_BIND_PORT = config('PA_PG_PORT', cast=int, default=0) +GOOGLE_RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') + +GITHUB_JWT = config('GITHUB_JWT') +GITHUB_REPO_PATH = config('DEV_GITHUB_REPO_PATH') + +OC_BACKEND_JWT_TOKEN = config('OC_BACKEND_JWT_TOKEN') +OC_BACKEND_URL = config('OC_BACKEND_URL') diff --git a/config/production.py b/config/production.py index 4937304..d7be40b 100644 --- a/config/production.py +++ b/config/production.py @@ -2,10 +2,10 @@ DEBUG = False -TOKEN = config('OPCODE_TOKEN') -VERIFICATION_TOKEN = config('OPCODE_VERIFICATION_TOKEN') -COMMUNITY_CHANNEL = config('OPCODE_COMMUNITY_ID') -MENTORS_INTERNAL_CHANNEL = config('OPCODE_MENTORS_INTERNAL_CHANNEL') +SLACK_TOKEN = config('OPCODE_TOKEN') +SLACK_VERIFICATION_TOKEN = config('OPCODE_VERIFICATION_TOKEN') +SLACK_COMMUNITY_CHANNEL = config('OPCODE_COMMUNITY_ID') +SLACK_MENTORS_INTERNAL_CHANNEL = config('OPCODE_MENTORS_INTERNAL_CHANNEL') AIRTABLE_BASE_KEY = config('OPCODE_AIRTABLE_BASE_KEY') AIRTABLE_API_KEY = config('OPCODE_AIRTABLE_TOKEN') @@ -17,6 +17,10 @@ DB_ADDR = config('PROD_DB_ADDR') DB_NAME = config('PROD_DB_NAME') -RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') +GOOGLE_RECAPTCHA_SECRET = config('RECAPTCHA_SECRET') + GITHUB_JWT = config('GITHUB_JWT') -GITHUB_REPO_PATH = config('GITHUB_REPO_PATH') \ No newline at end of file +GITHUB_REPO_PATH = config('GITHUB_REPO_PATH') + +OC_BACKEND_JWT_TOKEN = config('OC_BACKEND_JWT_TOKEN') +OC_BACKEND_URL = config('OC_BACKEND_URL') diff --git a/config/tests.py b/config/tests.py index 55c2d6d..8e2b983 100644 --- a/config/tests.py +++ b/config/tests.py @@ -2,10 +2,10 @@ PORT = 5000 -TOKEN = 'slack-token' -VERIFICATION_TOKEN = 'token' -COMMUNITY_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='community_channel') -MENTORS_INTERNAL_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='mentor_channel') +SLACK_TOKEN = 'slack-token' +SLACK_VERIFICATION_TOKEN = 'token' +SLACK_COMMUNITY_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='community_channel') +SLACK_MENTORS_INTERNAL_CHANNEL = config('DEV_PRIVATE_CHANNEL', default='mentor_channel') AIRTABLE_BASE_KEY = config('DEV_AIRTABLE_BASE_KEY', default='fake_airtable_base') AIRTABLE_API_KEY = config('DEV_AIRTABLE_TOKEN', default='fake_airtable_key') @@ -17,16 +17,10 @@ DB_ADDR = config('DEV_DB_ADDR', default='dev.db') DB_NAME = config('DEV_DB_NAME', default='') -PA_SSH_USERNAME = config('PA_SSH_USERNAME', default=None) -PA_SSH_PASSWORD = config('PA_SSH_PASSWORD', default=None) -PA_SSH_URL = config('PA_SSH_URL', default=None) -PA_SSH_REMOTE_BIND_ADDR = config('PA_PG_IP_ADDR', cast=str, default=None) -PA_SSH_REMOTE_BIND_PORT = config('PA_PG_PORT', cast=int, default=0) +GOOGLE_RECAPTCHA_SECRET = 'secret' -RECAPTCHA_SECRET = 'secret' GITHUB_JWT = 'jwt' GITHUB_REPO_PATH = config('DEV_GITHUB_REPO_PATH') -BACK_JWT_TOKEN = config('BACK_JWT_TOKEN') -OC_URL = config('OC_URL') -DEV_GITHUB_REPO_PATH = '' \ No newline at end of file +OC_BACKEND_JWT_TOKEN = config('OC_BACKEND_JWT_TOKEN') +OC_BACKEND_URL = config('OC_BACKEND_URL') diff --git a/ocbot/__init__.py b/ocbot/__init__.py index 6816926..ac408ce 100644 --- a/ocbot/__init__.py +++ b/ocbot/__init__.py @@ -2,7 +2,7 @@ import os from flask import Flask -from config.configs import configs +from config.all_config_loader import configs from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate diff --git a/ocbot/external/route_airtable.py b/ocbot/external/route_airtable.py index 63fac7b..1c8006c 100644 --- a/ocbot/external/route_airtable.py +++ b/ocbot/external/route_airtable.py @@ -3,7 +3,7 @@ from ocbot.external import ResponseContainer from requests import post, get, patch from functools import partial -from config.configs import configs +from config.all_config_loader import configs logger = logging.getLogger(__name__) diff --git a/ocbot/external/route_backend.py b/ocbot/external/route_backend.py index a1da71c..488bbad 100644 --- a/ocbot/external/route_backend.py +++ b/ocbot/external/route_backend.py @@ -2,11 +2,11 @@ import requests -from config.configs import configs +from config.all_config_loader import configs logger = logging.getLogger(__name__) -JWT_BACKEND_TOKEN = configs['BACK_JWT_TOKEN'] -OC_BACKEND_URL = configs['OC_URL'] +JWT_BACKEND_TOKEN = configs['OC_BACKEND_JWT_TOKEN'] +OC_BACKEND_URL = configs['OC_BACKEND_URL'] class OCBackend: diff --git a/ocbot/external/route_slack.py b/ocbot/external/route_slack.py index dd823e0..a790ba5 100644 --- a/ocbot/external/route_slack.py +++ b/ocbot/external/route_slack.py @@ -5,11 +5,11 @@ from slackclient import SlackClient -from config.configs import configs +from config.all_config_loader import configs from ocbot.external import ResponseContainer -VERIFICATION_TOKEN = configs['VERIFICATION_TOKEN'] -TOKEN = configs['TOKEN'] +VERIFICATION_TOKEN = configs['SLACK_VERIFICATION_TOKEN'] +TOKEN = configs['SLACK_TOKEN'] logger = logging.getLogger(__name__) diff --git a/ocbot/pipeline/handlers/airtable_request_handler.py b/ocbot/pipeline/handlers/airtable_request_handler.py index 6e407b5..877413a 100644 --- a/ocbot/pipeline/handlers/airtable_request_handler.py +++ b/ocbot/pipeline/handlers/airtable_request_handler.py @@ -4,9 +4,9 @@ from ocbot.external.route_airtable import AirTableBuilder, Airtable from ocbot.external.route_slack import SlackBuilder, Slack from ocbot.pipeline.handlers.abc import RouteHandler -from config.configs import configs +from config.all_config_loader import configs -MENTORS_INTERNAL_CHANNEL = configs['MENTORS_INTERNAL_CHANNEL'] +MENTORS_INTERNAL_CHANNEL = configs['SLACK_MENTORS_INTERNAL_CHANNEL'] class NewAirtableRequestHandler(RouteHandler): diff --git a/ocbot/pipeline/handlers/newmember.py b/ocbot/pipeline/handlers/newmember.py index a6859fa..81ace0e 100644 --- a/ocbot/pipeline/handlers/newmember.py +++ b/ocbot/pipeline/handlers/newmember.py @@ -1,9 +1,9 @@ from ocbot.external.route_slack import SlackBuilder, Slack from .abc import RouteHandler from ocbot.pipeline.utils import needs_greet_button -from config.configs import configs +from config.all_config_loader import configs -COMMUNITY_CHANNEL = configs['COMMUNITY_CHANNEL'] +COMMUNITY_CHANNEL = configs['SLACK_COMMUNITY_CHANNEL'] class NewMemberHandler(RouteHandler): diff --git a/ocbot/pipeline/handlers/suggestion.py b/ocbot/pipeline/handlers/suggestion.py index c6741cd..f430794 100644 --- a/ocbot/pipeline/handlers/suggestion.py +++ b/ocbot/pipeline/handlers/suggestion.py @@ -1,9 +1,9 @@ from ocbot.external.route_slack import Slack, SlackBuilder from .abc import RouteHandler -from config.configs import configs +from config.all_config_loader import configs -COMMUNITY_CHANNEL = configs['COMMUNITY_CHANNEL'] +COMMUNITY_CHANNEL = configs['SLACK_COMMUNITY_CHANNEL'] class SuggestionHandler(RouteHandler): """ diff --git a/ocbot/pipeline/web_api_handlers/handle_code_school.py b/ocbot/pipeline/web_api_handlers/handle_code_school.py index ce78d08..43da561 100644 --- a/ocbot/pipeline/web_api_handlers/handle_code_school.py +++ b/ocbot/pipeline/web_api_handlers/handle_code_school.py @@ -5,7 +5,7 @@ import requests from flask import jsonify -from config.configs import configs +from config.all_config_loader import configs recaptcha_secret = configs['RECAPTCHA_SECRET'] github_jwt = configs['GITHUB_JWT'] diff --git a/ocbot/web/routes_slack.py b/ocbot/web/routes_slack.py index 5ed86b6..c9235fc 100644 --- a/ocbot/web/routes_slack.py +++ b/ocbot/web/routes_slack.py @@ -3,7 +3,7 @@ from flask import request, make_response, json, redirect, url_for -from config.configs import configs +from config.all_config_loader import configs from ocbot import app from ocbot.pipeline.routing import RoutingHandler from ocbot.pipeline.slash_command_handlers.log_handlers import can_view_logs, get_temporary_url, handle_log_view @@ -11,7 +11,7 @@ from ocbot.pipeline.slash_command_handlers.testgreet_handler import can_test, create_testgreet_event from ocbot.web.route_decorators import url_verification, validate_response -VERIFICATION_TOKEN = configs['VERIFICATION_TOKEN'] +VERIFICATION_TOKEN = configs['SLACK_VERIFICATION_TOKEN'] logger = logging.getLogger(__name__) logger.level = logging.DEBUG diff --git a/ocbot/web/routes_web.py b/ocbot/web/routes_web.py index 21406f7..322569e 100644 --- a/ocbot/web/routes_web.py +++ b/ocbot/web/routes_web.py @@ -9,10 +9,10 @@ from werkzeug.datastructures import FileStorage from ocbot.pipeline.web_api_handlers.handle_code_school import handle_recaptcha_and_errors -from config.configs import configs +from config.all_config_loader import configs from ocbot import app -VERIFICATION_TOKEN = configs['VERIFICATION_TOKEN'] +VERIFICATION_TOKEN = configs['SLACK_VERIFICATION_TOKEN'] logger = logging.getLogger(__name__) logger.level = logging.DEBUG diff --git a/tests/external_tests/test_route_backend.py b/tests/external_tests/test_route_backend.py index 7e75ded..ba775f8 100644 --- a/tests/external_tests/test_route_backend.py +++ b/tests/external_tests/test_route_backend.py @@ -3,14 +3,14 @@ import pytest import pytest_mock -from config.configs import configs +from config.all_config_loader import configs from ocbot.external.route_backend import OCBackend, ExpiredTokenException, InvalidTokenException, \ UndecodableTokenException from tests.external_tests.test_route_backend_data import * logger = logging.getLogger(__name__) -CORRECT_TOKEN = configs['BACK_JWT_TOKEN'] +CORRECT_TOKEN = configs['OC_BACKEND_JWT_TOKEN'] # NOT A REAL TOKEN DONT TRY BITCHES BAD_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJzb21lIHJhbmRvbSBrZXkiLCJleHAiOjE4ODc1MjQ5Mzh9.cKikBK-AkMoIyAopLh1JjYi9cKyorkYE9FCX5LQHLy8' SHORT_TOKEN = 'a' diff --git a/tests/handler_tests/test_airtable_request.py b/tests/handler_tests/test_airtable_request.py index a5cfd6f..b489b25 100644 --- a/tests/handler_tests/test_airtable_request.py +++ b/tests/handler_tests/test_airtable_request.py @@ -2,7 +2,7 @@ import pytest_mock from ocbot.external.route_slack import Slack, SlackBuilder from ocbot.external.route_airtable import AirTableBuilder -from config.configs import configs +from config.all_config_loader import configs from ocbot.pipeline.handlers.airtable_request_handler import NewAirtableRequestHandler from tests.handler_tests.airtable_request_events import NEW_AIRTABLE_REQUEST_JSON, USER_ID_FROM_EMAIL_RESPONSE, \ @@ -12,7 +12,7 @@ SLACK_AUTH_TEST = 'ocbot.external.route_slack.Slack.auth_test' SLACK_GET_ID = 'ocbot.pipeline.handlers.airtable_request_handler.NewAirtableRequestHandler.check_user_id_cache' -MENTORS_INTERNAL_CHANNEL = configs['MENTORS_INTERNAL_CHANNEL'] +MENTORS_INTERNAL_CHANNEL = configs['SLACK_MENTORS_INTERNAL_CHANNEL'] SLACK_USER_ID = '<@AGF2354>' diff --git a/tests/test_flask.py b/tests/test_flask.py index 947dac3..52deb82 100644 --- a/tests/test_flask.py +++ b/tests/test_flask.py @@ -3,7 +3,7 @@ import logging import pytest -import config.configs +import config.all_config_loader import ocbot.web.routes_web import ocbot.web.routes_slack from tests import VALIDATE_RESPONSE_PATH, ROUTING_HANDLER_PATH, GOOD_TOKEN @@ -16,7 +16,7 @@ @pytest.fixture def test_app(): - config.configs.configs['VERIFICATION_TOKEN'] = GOOD_TOKEN + config.all_config_loader.configs['VERIFICATION_TOKEN'] = GOOD_TOKEN from ocbot import app app.config['TESTING'] = True app.config['WTF_CSRF_ENABLED'] = False From b84e7cbf2f27adf621755a42151f91b2cdb49b59 Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 28 May 2018 18:41:18 -0600 Subject: [PATCH 5/9] added .pytest_cache to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index be8d751..ff95449 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ venv/ __pycache__/ *.py[cod] *$py.class +.pytest_cache # Unit test / coverage reports From 7a0ffda30c8e47e482adfa900ba548cd1b3c162e Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 28 May 2018 19:43:08 -0600 Subject: [PATCH 6/9] Added tests for checking if any environment variables are not empty or 'default' --- config/all_config_loader.py | 1 + config/default.py | 30 ++++++++++----------- tests/environment_tests/__init__.py | 0 tests/environment_tests/test_credentials.py | 30 +++++++++++++++++++++ tests/external_tests/__init__.py | 0 5 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 tests/environment_tests/__init__.py create mode 100644 tests/environment_tests/test_credentials.py create mode 100644 tests/external_tests/__init__.py diff --git a/config/all_config_loader.py b/config/all_config_loader.py index 05e9d81..ea06ee6 100644 --- a/config/all_config_loader.py +++ b/config/all_config_loader.py @@ -9,6 +9,7 @@ configs.from_object('config.default') try: + print('config file', os.environ['CONFIG_FILE']) configs.from_envvar('CONFIG_FILE') except RuntimeError as ex: logger.warning("Failed to load config from envar") diff --git a/config/default.py b/config/default.py index 91247ee..bd4e924 100644 --- a/config/default.py +++ b/config/default.py @@ -4,25 +4,25 @@ PORT = 5000 -SLACK_VERIFICATION_TOKEN = 'default_verification_token' -SLACK_TOKEN = 'default_token' -SLACK_COMMUNITY_CHANNEL = 'default_community_channel' -SLACK_MENTORS_INTERNAL_CHANNEL = 'default_mentor_channel' +SLACK_VERIFICATION_TOKEN = 'default' +SLACK_TOKEN = 'default' +SLACK_COMMUNITY_CHANNEL = 'default' +SLACK_MENTORS_INTERNAL_CHANNEL = 'default' -AIRTABLE_BASE_KEY = 'default_fake_airtable_base' -AIRTABLE_API_KEY = 'default_fake_airtable_key' -AIRTABLE_TABLE_NAME = 'default Mentor Request' +AIRTABLE_BASE_KEY = 'default' +AIRTABLE_API_KEY = 'default' +AIRTABLE_TABLE_NAME = 'defaul' -DB_USERNAME = 'default_db_username' -DB_PASSWORD = 'default_db_password' -DB_DIALECT = 'defaultsqlite_dialect' -DB_ADDR = 'default_dev.db' -DB_NAME = 'default_db_name' +DB_USERNAME = 'default' +DB_PASSWORD = 'default' +DB_DIALECT = 'defaults' +DB_ADDR = 'default' +DB_NAME = 'default' -RECAPTCHA_SECRET = 'default' +GOOGLE_RECAPTCHA_SECRET = 'default' GITHUB_JWT = 'default' GITHUB_REPO_PATH = 'default' -OC_BACKEND_JWT_TOKEN = 'default_jwt_token' -OC_BACKEND_URL = 'default_oc_url' +OC_BACKEND_JWT_TOKEN = 'default' +OC_BACKEND_URL = 'default' diff --git a/tests/environment_tests/__init__.py b/tests/environment_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/environment_tests/test_credentials.py b/tests/environment_tests/test_credentials.py new file mode 100644 index 0000000..5295c52 --- /dev/null +++ b/tests/environment_tests/test_credentials.py @@ -0,0 +1,30 @@ +import logging +import os + +import pytest + +logger = logging.getLogger(__name__) + +from config.all_config_loader import configs + + +def test_using_development_config(): + os.environ['CONFIG_FILE'] = 'development.py' + assert (os.environ['CONFIG_FILE'] == 'development.py') + # from config.all_config_loader import configs + + +@pytest.mark.parametrize("test_input", [item for item in configs.keys()]) +def test_configs_not_default(test_input): + os.environ['CONFIG_FILE'] = 'development.py' + assert (os.environ['CONFIG_FILE'] == 'development.py') + from config.all_config_loader import configs + assert (configs[test_input] != 'default') + + +@pytest.mark.parametrize("test_input", [item for item in configs.keys()]) +def test_configs_not_empty(test_input): + os.environ['CONFIG_FILE'] = 'development.py' + assert (os.environ['CONFIG_FILE'] == 'development.py') + from config.all_config_loader import configs + assert (configs[test_input] != '') diff --git a/tests/external_tests/__init__.py b/tests/external_tests/__init__.py new file mode 100644 index 0000000..e69de29 From dce331384cf210c394ed1fd42ff936f7654fdebf Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 13 Aug 2018 10:08:03 -0600 Subject: [PATCH 7/9] checking any changes --- deploy/env_check | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 deploy/env_check diff --git a/deploy/env_check b/deploy/env_check new file mode 100644 index 0000000..e69de29 From c2a00c091fd40340b89813902bcf89b906abae15 Mon Sep 17 00:00:00 2001 From: wimo7083 Date: Mon, 13 Aug 2018 10:09:06 -0600 Subject: [PATCH 8/9] checkign for deltas --- deploy/env_check | 7 +++++++ ocbot/pipeline/web_api_handlers/handle_code_school.py | 2 +- tests/environment_tests/test_credentials.py | 11 +++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/deploy/env_check b/deploy/env_check index e69de29..7241b97 100644 --- a/deploy/env_check +++ b/deploy/env_check @@ -0,0 +1,7 @@ +#!/bin/bash + +AWS_VARS=eb printenv | sed -n 's/ *\([A-Z_]*\) =.*/\1/p' + +NEW_PROD_VARS=cat ../config/awsProd.py | sed '/#/d' |sed -n 's/ *\([A-Z_]\) =.*/\1/p' + +MISMATCH=comm -1 -3 Date: Mon, 13 Aug 2018 10:10:18 -0600 Subject: [PATCH 9/9] include required git files --- deploy/curr_prod | 25 +++++++++++++++++++++++++ deploy/prod | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 deploy/curr_prod create mode 100644 deploy/prod diff --git a/deploy/curr_prod b/deploy/curr_prod new file mode 100644 index 0000000..fb0b5c7 --- /dev/null +++ b/deploy/curr_prod @@ -0,0 +1,25 @@ +AWS_DEV_DB_ADDR +AWS_DEV_DB_DIALECT +AWS_DEV_DB_NAME +AWS_DEV_DB_PASSWORD +AWS_DEV_DB_USERNAME +CONFIG_FILE +DEV_AIRTABLE_BASE_KEY +DEV_AIRTABLE_TOKEN +DEV_AUTH_TOKEN +DEV_BOT_TOKEN +DEV_PRIVATE_CHANNEL +GITHUB_JWT +GITHUB_REPO_PATH +PROD_AIRTABLE_BASE_KEY +PROD_AIRTABLE_TOKEN +PROD_AUTH_TOKEN +PROD_BOT_TOKEN +PROD_COMMUNITY_CHANNEL +PROD_DB_ADDR +PROD_DB_DIALECT +PROD_DB_NAME +PROD_DB_PASSWORD +PROD_DB_USERNAME +PROD_MENTOR_CHANNEL +RECAPTCHA_SECRET diff --git a/deploy/prod b/deploy/prod new file mode 100644 index 0000000..cce0828 --- /dev/null +++ b/deploy/prod @@ -0,0 +1,18 @@ +DEBUG +SLACK_TOKEN +SLACK_VERIFICATION_TOKEN +SLACK_COMMUNITY_CHANNEL +SLACK_MENTORS_INTERNAL_CHANNEL +AIRTABLE_BASE_KEY +AIRTABLE_API_KEY +AIRTABLE_TABLE_NAME +DB_USERNAME +DB_PASSWORD +DB_DIALECT +DB_ADDR +DB_NAME +GOOGLE_RECAPTCHA_SECRET +GITHUB_JWT +GITHUB_REPO_PATH +OC_BACKEND_JWT_TOKEN +OC_BACKEND_URL