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
4 changes: 3 additions & 1 deletion 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 validate_user_auth_token_by_profile


@click.group(invoke_without_command=True)
Expand All @@ -16,11 +17,12 @@ 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)
validate_user_auth_token_by_profile(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
Expand Down
31 changes: 31 additions & 0 deletions evalai/utils/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,37 @@ def get_user_auth_token():
sys.exit(1)


def validate_user_auth_token_by_profile(auth_token):
hkmatsumoto marked this conversation as resolved.
Show resolved Hide resolved
"""
Checks tokens availability via server.
"""
url = "{}{}".format(get_host_url(), URLS.profile.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:
echo(
style(
"Failed: Unable to validate token.",
hkmatsumoto marked this conversation as resolved.
Show resolved Hide resolved
bold=True,
fg="red"
)
)
sys.exit(1)
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"
)
)
sys.exit(1)


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
"".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"
profile = "/api/auth/user"
hkmatsumoto marked this conversation as resolved.
Show resolved Hide resolved
challenge_list = "/api/challenges/challenge/all"
past_challenge_list = "/api/challenges/challenge/past"
future_challenge_list = "/api/challenges/challenge/future"
Expand Down
75 changes: 75 additions & 0 deletions tests/test_auth.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import json
import os
import random
import responses
import string

from beautifultable import BeautifulTable
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 Down Expand Up @@ -45,6 +48,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 = "".join(random.choice(string.ascii_lowercase + string.digits) for i in range(40))

url = "{}{}".format(API_HOST_URL, URLS.profile.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 = "".join(random.choice(string.ascii_lowercase + string.digits) for i in range(40))

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

self.expected = "Failed: Unable to validate 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 = "".join(random.choice(string.ascii_lowercase + string.digits) for i in range(40))
hkmatsumoto marked this conversation as resolved.
Show resolved Hide resolved

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 == self.expected


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

Expand Down