diff --git a/README.md b/README.md index 0fb3f2ef..b469ea7e 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,24 @@ Command line tool that allows the user to execute data operations on the platfor - Python - [Click](https://click.palletsprojects.com/en/8.0.x/) +## Getting Started + +### Prerequisites +- Python 3.7+ +- [Poetry](https://python-poetry.org/docs/#installation) + +#### Run with Python +1. Install dependencies (optional: run in edit mode). + ``` + poetry install + poetry run python app/pilotcli.py --help + ``` +2. Add environment variables if needed. + + 1. Create a `.env` file in the root directory of the project. + 2. Sdd following two environmental varibles to the `.env` file. + - `api_url`: the url that the api server is hosted on. default is `https://api.pilot.indocresearch.com/pilot` + - `keycloak_realm_url`: thr url that the keycloak server is hosted on. default is `https://iam.pilot.indocresearch.com/realms/pilot` #### Run from bundled application 1. Navigate to the appropriate directory for your system. @@ -17,14 +35,6 @@ Command line tool that allows the user to execute data operations on the platfor ./app/bundled_app/mac/ ./app/bundled_app/mac_arm/ -#### Run with Python -1. Install dependencies (optional: run in edit mode). - - poetry install - poetry run pilotcli - -2. Add environment variables if needed. - ## Usage ./app/bundled_app/linux/pilotcli --help diff --git a/app/configs/app_config.py b/app/configs/app_config.py index 79e4158f..85e59928 100644 --- a/app/configs/app_config.py +++ b/app/configs/app_config.py @@ -43,6 +43,7 @@ class Connections: url_validation = ConfigClass.url_validation url_keycloak = ConfigClass.url_keycloak url_keycloak_token = f'{ConfigClass.url_keycloak}/token' + url_keycloak_realm = ConfigClass.keycloak_realm_url url_bff = ConfigClass.url_bff - url_base = ConfigClass.base_url + url_base = ConfigClass.api_url url_portal = ConfigClass.url_portal diff --git a/app/configs/config.py b/app/configs/config.py index 04bbf98c..9b65018d 100644 --- a/app/configs/config.py +++ b/app/configs/config.py @@ -28,59 +28,52 @@ class Settings(BaseSettings): harbor_client_secret: str = '' url_harbor: str = '' - domain: str = 'pilot.indocresearch.com' - - @computed_field - def base_url(self) -> str: - return f'https://api.{self.domain}/pilot' + api_url: str = 'https://api.pilot.indocresearch.com/pilot' + keycloak_realm_url: str = 'https://iam.pilot.indocresearch.com/realms/pilot' @computed_field def url_bff(self) -> str: - return f'{self.base_url}/cli' + return f'{self.api_url}/cli' @computed_field def url_portal(self) -> str: - return f'{self.base_url}/portal' - - @computed_field - def url_keycloak_realm(self) -> str: - return f'https://iam.{self.domain}/realms/pilot' + return f'{self.api_url}/portal' @computed_field def url_keycloak(self) -> str: - return f'{self.url_keycloak_realm}/protocol/openid-connect' + return f'{self.keycloak_realm_url}/protocol/openid-connect' @computed_field def url_authn(self) -> str: - return f'{self.base_url}/portal/users/auth' + return f'{self.api_url}/portal/users/auth' @computed_field def url_refresh_token(self) -> str: - return f'{self.base_url}/portal/users/refresh' + return f'{self.api_url}/portal/users/refresh' @computed_field def url_file_tag(self) -> str: - return f'{self.base_url}/portal/v2/%s/tags' + return f'{self.api_url}/portal/v2/%s/tags' @computed_field def url_upload_greenroom(self) -> str: - return f'{self.base_url}/upload/gr' + return f'{self.api_url}/upload/gr' @computed_field def url_upload_core(self) -> str: - return f'{self.base_url}/upload/core' + return f'{self.api_url}/upload/core' @computed_field def url_status(self) -> str: - return f'{self.base_url}/portal/v1/files/actions/tasks' + return f'{self.api_url}/portal/v1/files/actions/tasks' @computed_field def url_download_greenroom(self) -> str: - return f'{self.base_url}/portal/download/gr/' + return f'{self.api_url}/portal/download/gr/' @computed_field def url_download_core(self) -> str: - return f'{self.base_url}/portal/download/core/' + return f'{self.api_url}/portal/download/core/' @computed_field def url_v2_download_pre(self) -> str: @@ -88,15 +81,15 @@ def url_v2_download_pre(self) -> str: @computed_field def url_dataset_v2download(self) -> str: - return f'{self.base_url}/portal/download/core/v2/dataset' + return f'{self.api_url}/portal/download/core/v2/dataset' @computed_field def url_dataset(self) -> str: - return f'{self.base_url}/portal/v1/dataset' + return f'{self.api_url}/portal/v1/dataset' @computed_field def url_validation(self) -> str: - return f'{self.base_url}/v1/files/validation' + return f'{self.api_url}/v1/files/validation' @lru_cache(1) diff --git a/app/services/user_authentication/user_login_logout.py b/app/services/user_authentication/user_login_logout.py index 33d71838..b4ca2bef 100644 --- a/app/services/user_authentication/user_login_logout.py +++ b/app/services/user_authentication/user_login_logout.py @@ -23,7 +23,7 @@ def exchange_api_key(api_key: str) -> Union[str, None]: """Exchange API Key with JWT token using Keycloak.""" - url = f'{ConfigClass.url_keycloak_realm}/api-key/{api_key}' + url = f'{AppConfig.Connections.url_keycloak_realm}/api-key/{api_key}' try: response = requests.get(url, timeout=5) response.raise_for_status() diff --git a/pyproject.toml b/pyproject.toml index 9154869f..5ec41f62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "app" -version = "2.9.3" +version = "2.9.4" description = "This service is designed to support pilot platform" authors = ["Indoc Systems"] diff --git a/tests/app/commands/test_user.py b/tests/app/commands/test_user.py index 3d2ff335..77b4b76d 100644 --- a/tests/app/commands/test_user.py +++ b/tests/app/commands/test_user.py @@ -5,6 +5,7 @@ import jwt from app.commands.user import login +from app.configs.app_config import AppConfig from app.configs.user_config import UserConfig @@ -14,7 +15,9 @@ def test_login_command_with_api_key_option_calls_keycloak_and_stores_response_in username = fake.user_name() api_key = fake.pystr(20) access_token = jwt.encode({'preferred_username': username}, key='').decode() - requests_mock.get(f'{settings.url_keycloak_realm}/api-key/{api_key}', json={'access_token': access_token}) + requests_mock.get( + f'{AppConfig.Connections.url_keycloak_realm}/api-key/{api_key}', json={'access_token': access_token} + ) result = cli_runner.invoke(login, ['--api-key', api_key]) diff --git a/tests/app/services/user_authentication/test_token_manager.py b/tests/app/services/user_authentication/test_token_manager.py index 6846ae20..049a26d5 100644 --- a/tests/app/services/user_authentication/test_token_manager.py +++ b/tests/app/services/user_authentication/test_token_manager.py @@ -33,7 +33,7 @@ def test_refresh_api_key_calls_keycloak_and_stores_access_token_in_config(self, manager = SrvTokenManager() access_token = jwt.encode({}, key='').decode() requests_mock.get( - f'{settings.url_keycloak_realm}/api-key/{manager.config.api_key}', + f'{AppConfig.Connections.url_keycloak_realm}/api-key/{manager.config.api_key}', json={'access_token': access_token}, ) diff --git a/tests/conftest.py b/tests/conftest.py index 8c74fa46..6755b434 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,6 +27,7 @@ def mock_settings(monkeypatch, mocker): monkeypatch.setattr(AppConfig.Connections, 'url_download_core', 'http://url_dataset_download_core') monkeypatch.setattr(AppConfig.Connections, 'url_upload_greenroom', 'http://upload_gr') monkeypatch.setattr(AppConfig.Connections, 'url_upload_core', 'http://upload_core') + monkeypatch.setattr(AppConfig.Connections, 'url_keycloak_realm', 'http://url_keycloak_realm') monkeypatch.setattr(UserConfig, 'username', 'test-user') monkeypatch.setattr(UserConfig, 'password', 'test-password') monkeypatch.setattr(UserConfig, 'api_key', 'test-api-key')