diff --git a/importer/README.md b/importer/README.md index 74de0683..20fc997d 100644 --- a/importer/README.md +++ b/importer/README.md @@ -17,7 +17,7 @@ This script is used to setup keycloak roles and groups. It takes in a csv file w ### To run script 1. Create virtualenv 2. Install requirements.txt - `pip install -r requirements.txt` -3. Create a `config.py` file. The `sample_config.py` is an example of what this should look like. Populate it with the right credentials. Ensure that the user whose details you provide in this config file has the necessary permissions/privilleges to setup/create Keycloak roles and groups. +3. Create a `config.py` file. The `sample_config.py` is an example of what this should look like. Populate it with the right credentials, you can either provide an access token or client credentials. Ensure that the user whose details you provide in this config file has the necessary permissions/privilleges. 4. Run script - `python3 main.py --setup roles --csv_file csv/setup/roles.csv --group Supervisor` 5. If you are running the script without `https` setup e.g locally or a server without https setup, you will need to set the `OAUTHLIB_INSECURE_TRANSPORT` environment variable to 1. For example `export OAUTHLIB_INSECURE_TRANSPORT=1 && python3 main.py --setup roles --csv_file csv/setup/roles.csv --group OpenSRP_Provider --log_level debug` 6. You can turn on logging by passing a `--log_level` to the command line as `info`, `debug` or `error`. For example `python3 main.py --setup roles --csv_file csv/setup/roles.csv --group Supervisor --log_level debug` diff --git a/importer/main.py b/importer/main.py index acc128dc..69e40450 100644 --- a/importer/main.py +++ b/importer/main.py @@ -15,6 +15,7 @@ logging.error("The config.py file is missing!") exit() +global_access_token = "" # This function takes in a csv file # reads it and returns a list of strings/lines @@ -37,6 +38,39 @@ def read_csv(csv_file): logging.error("Stop iteration on empty file") +def get_access_token(): + access_token = "" + if global_access_token: + return global_access_token + + try: + if config.access_token: + # get access token from config file + access_token = config.access_token + except AttributeError: + logging.debug("No access token provided, trying to use client credentials") + + if not access_token: + # get client credentials from config file + client_id = config.client_id + client_secret = config.client_secret + username = config.username + password = config.password + access_token_url = config.access_token_url + + oauth = OAuth2Session(client=LegacyApplicationClient(client_id=client_id)) + token = oauth.fetch_token( + token_url=access_token_url, + username=username, + password=password, + client_id=client_id, + client_secret=client_secret, + ) + access_token = token["access_token"] + + return access_token + + # This function makes the request to the provided url # to create resources @backoff.on_exception(backoff.expo, requests.exceptions.RequestException, max_time=180) @@ -46,23 +80,7 @@ def post_request(request_type, payload, url): logging.info("Url: " + url) logging.debug("Payload: " + payload) - # get credentials from config file - client_id = config.client_id - client_secret = config.client_secret - username = config.username - password = config.password - access_token_url = config.access_token_url - - oauth = OAuth2Session(client=LegacyApplicationClient(client_id=client_id)) - token = oauth.fetch_token( - token_url=access_token_url, - username=username, - password=password, - client_id=client_id, - client_secret=client_secret, - ) - - access_token = "Bearer " + token["access_token"] + access_token = "Bearer " + get_access_token() headers = {"Content-type": "application/json", "Authorization": access_token} if request_type == "POST": @@ -845,6 +863,7 @@ def clean_duplicates(users, cascade_delete): @click.command() @click.option("--csv_file", required=True) +@click.option("--access_token", required=False) @click.option("--resource_type", required=False) @click.option("--assign", required=False) @click.option("--setup", required=False) @@ -856,7 +875,7 @@ def clean_duplicates(users, cascade_delete): "--log_level", type=click.Choice(["DEBUG", "INFO", "ERROR"], case_sensitive=False) ) def main( - csv_file, resource_type, assign, setup, group, roles_max, cascade_delete, only_response, log_level + csv_file, access_token, resource_type, assign, setup, group, roles_max, cascade_delete, only_response, log_level ): if log_level == "DEBUG": logging.basicConfig(level=logging.DEBUG) @@ -870,6 +889,11 @@ def main( final_response = "" + # set access token + if access_token: + global global_access_token + global_access_token = access_token + logging.info("Starting csv import...") resource_list = read_csv(csv_file) if resource_list: diff --git a/importer/sample_config.py b/importer/sample_config.py index f2642368..d46cc9ac 100644 --- a/importer/sample_config.py +++ b/importer/sample_config.py @@ -5,3 +5,4 @@ access_token_url = 'https://keycloak.smartregister.org/auth/realms/example-realm/protocol/openid-connect/token' fhir_base_url = 'https://example.smartregister.org/fhir' keycloak_url = 'https://keycloak.smartregister.org/auth/admin/realms/example-realm' +access_token = 'example-access-token'