From 2437b66f76467b823ec3aeee75a71f0c25752363 Mon Sep 17 00:00:00 2001
From: Luc Guyot <luc.guyot@epfl.ch>
Date: Mon, 29 Apr 2019 14:39:07 +0000
Subject: [PATCH] Merged in NRRPLT-7296 (pull request #13)

[NRRPLT-7296] Allows instantiation of the VirtualCoach based on the OIDC token only

* [NRRPLT-7296] Allows instantiation of the VirtualCoach based on the OIDC token only

* [NRRPLT-7296] Fixes pep8 errors

Approved-by: Claudio Sousa <claudio.sousa@gmail.com>
Approved-by: Susie Murphy <susie.murphy@epfl.ch>
---
 .../hbp_nrp_virtual_coach/oidc_http_client.py    | 16 +++++++++++++---
 .../tests/test_virtual_coach.py                  | 11 +++++++++--
 .../hbp_nrp_virtual_coach/virtual_coach.py       | 16 +++++++++++-----
 3 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/oidc_http_client.py b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/oidc_http_client.py
index 66faf0c..4539d77 100644
--- a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/oidc_http_client.py
+++ b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/oidc_http_client.py
@@ -7,12 +7,22 @@ import json
 class OIDCHTTPClient(HTTPClient):
     """ Class which uses the BBP oidc client to do http calls """
 
-    def __init__(self, oidc_username):
+    def __init__(self, oidc_username=None, oidc_token=None):
         """
-        :param oidc_username: The HBP oidc username
+        :param oidc_username: (optional) The HBP oidc username, required if the token is omitted
+        :param oidc_token: (optional) The HBP oidc token, required if the username is omitted
         """
         from bbp_client.oidc.client import BBPOIDCClient
-        self.__oidc_client = BBPOIDCClient.implicit_auth(oidc_username)
+        if not oidc_username and not oidc_token:
+            raise ValueError(
+                "You need to specify either an oidc_username"
+                " or a token in order to instantiate OIDCHTTPClient."
+            )
+
+        if oidc_username:
+            self.__oidc_client = BBPOIDCClient.implicit_auth(oidc_username)
+        elif oidc_token:
+            self.__oidc_client = BBPOIDCClient.bearer_auth(oauth_url=None, token=oidc_token)
         self.__headers = None
 
     def get(self, url):
diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py
index 9f25da1..f85c541 100644
--- a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py
+++ b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py
@@ -120,13 +120,20 @@ class TestVirtualCoach(unittest.TestCase):
         self._mock_exp_list_cloned = [{'uuid': 'MockExperiment1_0', 'name': 'MockExperiment1_0'},
                                       {'uuid': 'MockExperiment2_0', 'name': 'MockExperiment2_0'}]
 
+
+    def test_init_asserts_no_password(self):
+        # invalid oidc token
+        self.assertRaises(AssertionError, VirtualCoach, oidc_token=123)
+
+        # invalid environment
+        self.assertRaises(AssertionError, VirtualCoach, environment=True)
+
+
     @patch('getpass.getpass', return_value='password')
     def test_init_asserts(self, mock_getpass):
         # invalid oidc username
         self.assertRaises(AssertionError, VirtualCoach, oidc_username=123)
 
-        # invalid environment
-        self.assertRaises(AssertionError, VirtualCoach, environment=True)
 
         # invalid storage server username
         self.assertRaises(AssertionError, VirtualCoach, storage_username=123)
diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py
index 221be57..ba5b858 100644
--- a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py
+++ b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py
@@ -52,7 +52,7 @@ class VirtualCoach(object):
     view available experiments, query currently running experiments, launch a simulation, and more.
     """
 
-    def __init__(self, environment=None, oidc_username=None,
+    def __init__(self, environment=None, oidc_username=None, oidc_token=None,
                  storage_username=None, storage_password=None):
         """
         Instantiates the Virtual Coach by loading the configuration file and logging into OIDC for
@@ -66,8 +66,12 @@ class VirtualCoach(object):
                             a key/value pair to the "proxy" section.
         :param oidc_username: (optional) A string representing the OIDC username for the current
                               user, required if the provided environment requires OIDC
-                              authentication. The user will be interactively asked for a password by
+                              authentication and no token is provided.
+                              The user will be interactively asked for a password by
                               the OIDC client if the token is expired or they have not logged in.
+        :param oidc_token: (optional) A string representing the OIDC token for the current
+                              user, required if the selected environment requires OIDC
+                              and the username is not provided.
         :param storage_username: (optional) A string representing the Storage Server username. It is
                                  required if the user wants to have access to the storage server to
                                  clone experiments and launch cloned experiments.
@@ -76,6 +80,7 @@ class VirtualCoach(object):
         """
         assert isinstance(environment, (str, type(None)))
         assert isinstance(oidc_username, (str, type(None)))
+        assert isinstance(oidc_token, (str, type(None)))
         assert isinstance(storage_username, (str, type(None)))
 
         # ROS node and logger configuration only if rospy is available
@@ -105,10 +110,11 @@ class VirtualCoach(object):
         self.__oidc_username = oidc_username
         self.__storage_username = storage_username
         # if an OIDC username is provided, attempt to login or retrieve the last valid token
-        if oidc_username:
+        if oidc_username or oidc_token:
             # this will interactively prompt the user for a password in terminal if needed
-            logger.info('Logging into OIDC as: %s', oidc_username)
-            self.__http_client = OIDCHTTPClient(oidc_username)
+            if oidc_username:
+                logger.info('Logging into OIDC as: %s', oidc_username)
+            self.__http_client = OIDCHTTPClient(oidc_username=oidc_username, oidc_token=oidc_token)
 
             authorization = self.__http_client.get_auth_header()
             # Set self.__http_headers: it is also used
-- 
GitLab