Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add token collation using server-obtained token #186

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
30 changes: 20 additions & 10 deletions evalai/add_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from click import echo, style

from evalai.utils.config import AUTH_TOKEN_DIR, AUTH_TOKEN_PATH, LEN_OF_TOKEN
from evalai.utils.auth import is_auth_token_valid


@click.group(invoke_without_command=True)
Expand All @@ -16,23 +17,32 @@ def set_token(auth_token):
Configure EvalAI Token.
"""
"""
Invoked by `evalai settoken <your_evalai_auth_token>`.
Invoked by `evalai set_token <your_evalai_auth_token>`.
"""
if validators.length(auth_token, min=LEN_OF_TOKEN, max=LEN_OF_TOKEN):
if not os.path.exists(AUTH_TOKEN_DIR):
os.makedirs(AUTH_TOKEN_DIR)
with open(AUTH_TOKEN_PATH, "w+") as fw:
try:
auth_token = {"token": "{}".format(auth_token)} # noqa
auth_token = json.dumps(auth_token)
fw.write(auth_token)
except (OSError, IOError) as e:
echo(e)
if is_auth_token_valid(auth_token):
hkmatsumoto marked this conversation as resolved.
Show resolved Hide resolved
with open(AUTH_TOKEN_PATH, "w+") as fw:
try:
auth_token = {"token": "{}".format(auth_token)} # noqa
auth_token = json.dumps(auth_token)
fw.write(auth_token)
except (OSError, IOError) as e:
echo(e)
echo(
style(
"Success: Authentication token is successfully set.",
bold=True,
fg="green",
)
)
else:
echo(
style(
"Success: Authentication token is successfully set.",
"Error: Invalid Auth Token (unrecognized or wrong Auth Token).",
bold=True,
fg="green",
fg="red"
)
)
else:
Expand Down
25 changes: 25 additions & 0 deletions evalai/utils/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,31 @@ def get_user_auth_token():
sys.exit(1)


def is_auth_token_valid(auth_token):
"""
Returns if token is available via server.
"""
url = "{}{}".format(get_host_url(), URLS.validate_auth_token.value)
try:
headers = {"Authorization": "Token {}".format(auth_token)}
response = requests.post(url, headers=headers)
response.raise_for_status()
except requests.exceptions.HTTPError:
if response.status_code in EVALAI_ERROR_CODES:
return False
except requests.exceptions.RequestException:
echo(
style(
"\nCould not establish a connection to EvalAI."
" Please check the Host URL: {}\n".format(get_host_url()),
bold=True,
fg="red"
)
)
return False
return True
hkmatsumoto marked this conversation as resolved.
Show resolved Hide resolved


def get_request_header():
"""
Returns user auth token formatted in header for sending requests.
Expand Down
7 changes: 7 additions & 0 deletions evalai/utils/common.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random
import string
import sys
import click

Expand Down Expand Up @@ -88,3 +90,8 @@ def clean_data(data):

def notify_user(message, color="green", bold=False):
echo(style(message, fg=color, bold=bold))


def generate_random_string(length):
letter_set = string.ascii_lowercase + string.digits
return "".join(random.choice(letter_set) for _ in range(length))
1 change: 1 addition & 0 deletions evalai/utils/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

class URLS(Enum):
login = "/api/auth/login"
validate_auth_token = "/api/auth/user"
challenge_list = "/api/challenges/challenge/all"
past_challenge_list = "/api/challenges/challenge/past"
future_challenge_list = "/api/challenges/challenge/future"
Expand Down
75 changes: 74 additions & 1 deletion tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from click.testing import CliRunner

from evalai.challenges import challenge, challenges
from evalai.add_token import set_token
from evalai.set_host import host
from evalai.utils.urls import URLS
from evalai.utils.config import (
Expand All @@ -14,7 +15,7 @@
AUTH_TOKEN_FILE_NAME,
HOST_URL_FILE_PATH,
)
from evalai.utils.common import convert_UTC_date_to_local
from evalai.utils.common import convert_UTC_date_to_local, generate_random_string

from tests.data import challenge_response
from tests.base import BaseTestClass
Expand Down Expand Up @@ -45,6 +46,78 @@ def test_get_user_auth_token_when_file_does_not_exist(self):
assert response == expected


class TestValidateUserAuthTokenByProfileWithValidToken(BaseTestClass):
def setup(self):
self.token_data = generate_random_string(40)

url = "{}{}".format(API_HOST_URL, URLS.validate_auth_token.value)
headers = {"Authorization": "Token {}".format(self.token_data)}
responses.add(
responses.POST,
url,
headers=headers,
status=200,
)

self.expected = "Success: Authentication token is successfully set.\n"

@responses.activate
def test_validate_user_auth_token_by_profile_when_token_is_valid(self):
runner = CliRunner()
result = runner.invoke(set_token, [self.token_data])
response = result.output
assert response == self.expected


class TestValidateUserAuthTokenByProfileWithInvalidToken(BaseTestClass):
def setup(self):
self.token_data = generate_random_string(40)

url = "{}{}".format(API_HOST_URL, URLS.validate_auth_token.value)
headers = {"Authorization": "Token".format(self.token_data)}
responses.add(
responses.POST,
url,
headers=headers,
status=401,
)

self.expected = "Error: Invalid Auth Token (unrecognized or wrong Auth Token).\n"

@responses.activate
def test_validate_user_auth_token_by_profile_when_token_is_invalid(self):
runner = CliRunner()
result = runner.invoke(set_token, [self.token_data])
response = result.output
assert response == self.expected


class TestValidateUserAuthTokenByProfileWithBrokenURL(BaseTestClass):
def setup(self):
self.token_data = generate_random_string(40)

url = "i-am-broken-url"
headers = {"Authorization": "Token".format(self.token_data)}
responses.add(
responses.POST,
url,
headers=headers,
status=401,
)

self.expected = (
"\nCould not establish a connection to EvalAI."
" Please check the Host URL: {}\n\n".format(API_HOST_URL)
)

@responses.activate
def test_validate_user_auth_token_by_profile_when_url_is_broken(self):
runner = CliRunner()
result = runner.invoke(set_token, [self.token_data])
response = result.output
assert response.startswith(self.expected)


class TestUserRequestWithInvalidToken(BaseTestClass):
def setup(self):

Expand Down