import pytest

from base64 import b64encode

from auth.basic import validate_basic_auth, ACCESS_TOKEN_USERNAME, OAUTH_TOKEN_USERNAME
from auth.validateresult import AuthKind, ValidateResult
from data import model

from test.fixtures import *

def _token(username, password):
  return 'basic ' + b64encode('%s:%s' % (username, password))

@pytest.mark.parametrize('token, expected_result', [
  ('', ValidateResult(AuthKind.basic, missing=True)),
  ('someinvalidtoken', ValidateResult(AuthKind.basic, missing=True)),
  ('somefoobartoken', ValidateResult(AuthKind.basic, missing=True)),
  ('basic ', ValidateResult(AuthKind.basic, missing=True)),
  ('basic some token', ValidateResult(AuthKind.basic, missing=True)),
  ('basic sometoken', ValidateResult(AuthKind.basic, missing=True)),

  (_token(ACCESS_TOKEN_USERNAME, 'invalid'),
   ValidateResult(AuthKind.basic, error_message='Invalid access token')),

  (_token(OAUTH_TOKEN_USERNAME, 'invalid'),
   ValidateResult(AuthKind.oauth, error_message='OAuth access token could not be validated')),

  (_token('devtable', 'invalid'),
   ValidateResult(AuthKind.basic, error_message='Invalid Username or Password')),

  (_token('devtable+somebot', 'invalid'),
   ValidateResult(AuthKind.basic,
                  error_message='Could not find robot with username: devtable+somebot ' +
                                'and supplied password.')),

  (_token('disabled', 'password'),
   ValidateResult(AuthKind.basic,
                  error_message='This user has been disabled. Please contact your administrator.')),
])
def test_validate_basic_auth_token(token, expected_result, app):
  result = validate_basic_auth(token)
  assert result == expected_result


def test_valid_user(app):
  token = _token('devtable', 'password')
  result = validate_basic_auth(token)
  assert result == ValidateResult(AuthKind.basic, user=model.user.get_user('devtable'))


def test_valid_robot(app):
  robot, password = model.user.create_robot('somerobot', model.user.get_user('devtable'))
  token = _token(robot.username, password)
  result = validate_basic_auth(token)
  assert result == ValidateResult(AuthKind.basic, robot=robot)


def test_valid_token(app):
  access_token = model.token.create_delegate_token('devtable', 'simple', 'sometoken')
  token = _token(ACCESS_TOKEN_USERNAME, access_token.code)
  result = validate_basic_auth(token)
  assert result == ValidateResult(AuthKind.basic, token=access_token)


def test_valid_oauth(app):
  user = model.user.get_user('devtable')
  oauth_token = list(model.oauth.list_access_tokens_for_user(user))[0]
  token = _token(OAUTH_TOKEN_USERNAME, oauth_token.access_token)
  result = validate_basic_auth(token)
  assert result == ValidateResult(AuthKind.oauth, oauthtoken=oauth_token)