#encoding:UTF-8

""" Run these tests with 'python manage.py test text'  """

from ldt.test.testcases import TestCase
from ldt.text import VERSION_STR
from oauth2 import Request, SignatureMethod_HMAC_SHA1, generate_nonce
from oauth_provider.consts import OUT_OF_BAND
from oauth_provider.models import Consumer, Token
import datetime
import lxml.etree
import time
import urlparse

CONSUMER_KEY = 'dpf43f3p2l4k3l03'
CONSUMER_SECRET = 'kd94hf93k423kf44'

        
class OAuthTestDelete(TestCase):
    
    fixtures = ['oauth_data', 'base_data']
    
    def setUp(self):

        self.nonce = generate_nonce(8)
        
        self.parameters_request = {
            'oauth_consumer_key': CONSUMER_KEY,
            'oauth_signature_method': 'PLAINTEXT',
            'oauth_signature': '%s&' % CONSUMER_SECRET,
            'oauth_timestamp': str(int(time.time())),
            'oauth_nonce': self.nonce,
            'oauth_version': '1.0',
            'oauth_callback': OUT_OF_BAND,
        }
        
        self.parameters_access = {
            'oauth_consumer_key': CONSUMER_KEY,
            'oauth_signature_method': 'PLAINTEXT',
            'oauth_nonce': self.nonce,
            'oauth_version': '1.0',
        }
        
        self.parameters_protected = {
            'oauth_consumer_key': CONSUMER_KEY,
            'oauth_signature_method': 'HMAC-SHA1',
            'oauth_nonce': self.nonce,
            'oauth_version': '1.0',
        }
        
        
    def test_auth_access_delete(self):
        
        ## REQUEST TOKEN     
        self.parameters_request['scope'] = 'delete'
        
        response = self.client.get("http://127.0.0.1:8000/oauth/request_token/", self.parameters_request)
        self.assertEqual(response.status_code, 200)
           
        token = list(Token.objects.all())[-1]
        data = urlparse.parse_qs(response.content)
        
        self.assertEqual(token.key, data["oauth_token"][0])
        self.assertEqual(token.secret, data['oauth_token_secret'][0])
        self.assertTrue(data['oauth_callback_confirmed'][0])
        self.assertEqual(token.callback, None)

        ## USER AUTHORIZATION
        parameters = {
            'oauth_token': token.key,
        }
        
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(token.key in response['Location'])
        
        self.client.login(username='jane', password='toto')
        
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Fake authorize view for example.com.')
    
        # fake authorization by the user
        parameters['authorize_access'] = 1
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 200)
        
        token = list(Token.objects.all())[-1]
        self.assertTrue(token.is_approved)
        
        ## ACCESS TOKEN
        self.parameters_access['oauth_token'] = token.key
        self.parameters_access['oauth_signature'] = '%s&%s' % (CONSUMER_SECRET, token.secret)
        self.parameters_access['oauth_timestamp'] = str(int(time.time()))
        self.parameters_access['oauth_verifier'] = token.verifier
        self.parameters_access['scope'] = 'delete'
        
        response = self.client.get("/oauth/access_token/", self.parameters_access)
        
        access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]
        self.assertTrue(access_token.key in response.content)
        self.assertTrue(access_token.secret in response.content)
        self.assertEqual(access_token.user.username, u'jane')
        
        ## ACCESSING PROTECTED VIEW
        self.parameters_protected['oauth_token'] = access_token.key
        self.parameters_protected['oauth_timestamp'] = str(int(time.time()))
        
        oauth_request = Request.from_token_and_callback(access_token, http_url='http://testserver/api/' + VERSION_STR + '/text/delete/z2c1d1fa-629d-4520-a3d2-955b4f2582c0', parameters=self.parameters_protected, http_method="DELETE")
        signature_method = SignatureMethod_HMAC_SHA1()
        signature = signature_method.sign(oauth_request, Consumer.objects.get(name="example.com"), access_token)

        self.parameters_protected['oauth_signature'] = signature
        response = self.client.delete("/api/" + VERSION_STR + "/text/delete/z2c1d1fa-629d-4520-a3d2-955b4f2582c0", self.parameters_protected)
        self.assertEqual(response.content, "")
        self.assertEqual(response.status_code, 200)
        
        self.client.logout()
        access_token.delete()
        
    
    def test_auth_access_create(self):
        
        ## REQUEST TOKEN
        self.parameters_request['scope'] = 'create'
        response = self.client.get("/oauth/request_token/", self.parameters_request)
        self.assertEqual(response.status_code, 200)   
        token = list(Token.objects.all())[-1]
        data = urlparse.parse_qs(response.content)
        self.assertEqual(token.key, data["oauth_token"][0])
        self.assertEqual(token.secret, data['oauth_token_secret'][0])
        self.assertTrue(data['oauth_callback_confirmed'][0])
        self.assertEqual(token.callback, None)

        ## USER AUTHORIZATION
        parameters = {
            'oauth_token': token.key,
        }
        
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(token.key in response['Location'])
        
        self.client.login(username='jane', password='toto')
        
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Fake authorize view for example.com.')
    
        # fake authorization by the user
        parameters['authorize_access'] = 1
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 200)
        token = list(Token.objects.all())[-1]
        self.assertTrue(token.is_approved)
        
        ## ACCESS TOKEN
        self.parameters_access['oauth_token'] = token.key
        self.parameters_access['oauth_signature'] = '%s&%s' % (CONSUMER_SECRET, token.secret)
        self.parameters_access['oauth_timestamp'] = str(int(time.time()))
        self.parameters_access['oauth_verifier'] = token.verifier
        self.parameters_access['scope'] = 'create'
        
        response = self.client.get("/oauth/access_token/", self.parameters_access)
        
        access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]
        self.assertTrue(access_token.key in response.content)
        self.assertTrue(access_token.secret in response.content)
        self.assertEqual(access_token.user.username, u'jane')
        
        ## ACCESSING PROTECTED VIEW
        self.parameters_protected['oauth_token'] = access_token.key
        self.parameters_protected['oauth_timestamp'] = str(int(time.time()))
        self.parameters_protected['content'] = '<iri><text-annotation><id>f2c1d1fa-629d-4520-a3d2-955b4f2582c0</id><uri>http://www.leezam.com/pub/epub/123456!/OPS/chapter2.xhtml#pos=56,168</uri><tags><tag>tag1</tag><tag>tag2</tag></tags><content><color>#AAAAAA</color><description><![CDATA[texte de description]]></description><title><![CDATA[titre de l\'annotation]]></title><text><![CDATA[texte selectionne lors de la creation de l\'annotation]]></text></content><meta><contributor>oaubert</contributor><contributor-id>79cd0532-1dda-4130-b351-6a181130a7c9</contributor-id><created>2010-09-06 12:33:53.417550</created><creator>oaubert</creator><creator-id>79cd0532-1dda-4130-b351-6a181130a7c9</creator-id><modified>2010-09-06 12:33:53.420459</modified></meta></text-annotation></iri>'
        
        oauth_request = Request.from_token_and_callback(access_token, http_url='http://testserver/api/' + VERSION_STR + '/text/create/', parameters=self.parameters_protected, http_method="POST")
        signature_method = SignatureMethod_HMAC_SHA1()
        signature = signature_method.sign(oauth_request, Consumer.objects.get(name="example.com"), access_token)

        self.parameters_protected['oauth_signature'] = signature
        response = self.client.post("/api/" + VERSION_STR + "/text/create/", self.parameters_protected)
        annot1 = lxml.etree.fromstring(response.content)
        self.assertEqual(annot1.xpath("/iri/text-annotation/meta/created/text()")[0][:11], str(datetime.datetime.now())[:11])
        self.assertEqual(response.status_code, 200)
        
        self.client.logout()
        access_token.delete()

    def test_auth_access_update(self):
        
        ## REQUEST TOKEN
        self.parameters_request['scope'] = 'update'
        
        response = self.client.get("/oauth/request_token/", self.parameters_request)
        self.assertEqual(response.status_code, 200)   
        
        token = list(Token.objects.all())[-1]
        data = urlparse.parse_qs(response.content)
        self.assertEqual(token.key, data["oauth_token"][0])
        self.assertEqual(token.secret, data['oauth_token_secret'][0])
        self.assertTrue(data['oauth_callback_confirmed'][0])
        self.assertEqual(token.callback, None)

        ## USER AUTHORIZATION
        parameters = {
            'oauth_token': token.key,
        }
        
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 302)
        self.assertTrue(token.key in response['Location'])
        
        self.client.login(username='jane', password='toto')
        
        response = self.client.get("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, 'Fake authorize view for example.com.')
    
        # fake authorization by the user
        parameters['authorize_access'] = 1
        response = self.client.post("/oauth/authorize/", parameters)
        self.assertEqual(response.status_code, 200)
        token = list(Token.objects.all())[-1]
        self.assertTrue(token.is_approved)
        
        ## ACCESS TOKEN
        self.parameters_access['oauth_token'] = token.key
        self.parameters_access['oauth_signature'] = '%s&%s' % (CONSUMER_SECRET, token.secret)
        self.parameters_access['oauth_timestamp'] = str(int(time.time()))
        self.parameters_access['oauth_verifier'] = token.verifier
        self.parameters_access['scope'] = 'update'
        
        response = self.client.get("/oauth/access_token/", self.parameters_access)
        
        access_token = list(Token.objects.filter(token_type=Token.ACCESS))[-1]
        self.assertTrue(access_token.key in response.content)
        self.assertTrue(access_token.secret in response.content)
        self.assertEqual(access_token.user.username, u'jane')
        
        ## ACCESSING PROTECTED VIEW
        self.parameters_protected['oauth_token'] = access_token.key
        self.parameters_protected['oauth_timestamp'] = str(int(time.time()))
        self.parameters_protected['content'] = '<iri><text-annotation><id></id><uri></uri><tags><tag>tag2new</tag><tag>mytag</tag></tags><content><color>#DDDDDD</color><description><![CDATA[texte de description update]]></description><title></title><text><![CDATA[texte selectionne a nouveau lors de la creation de l\'annotation]]></text></content><meta><contributor>oaubert</contributor><contributor-id>80cd0532-1dda-4130-b351-6a181130a7c9</contributor-id><created></created><creator></creator><creator-id></creator-id><modified>2010-11-06 12:33:53.420459</modified></meta></text-annotation></iri>'
        
        oauth_request = Request.from_token_and_callback(access_token, http_url='http://testserver/api/' + VERSION_STR + '/text/update/z2c1d1fa-629d-4520-a3d2-955b4f2582c0', parameters=self.parameters_protected, http_method="PUT")
        signature_method = SignatureMethod_HMAC_SHA1()
        signature = signature_method.sign(oauth_request, Consumer.objects.get(name="example.com"), access_token)

        self.parameters_protected['oauth_signature'] = signature
        response = self.client.put("/api/" + VERSION_STR + "/text/update/z2c1d1fa-629d-4520-a3d2-955b4f2582c0", self.parameters_protected)
        doc = lxml.etree.fromstring(response.content)
        self.assertEqual(doc.xpath("/iri/text-annotation/id/text()")[0], "z2c1d1fa-629d-4520-a3d2-955b4f2582c0")
        self.assertTrue('tag3', 'tag1' not in doc.xpath("/iri/text-annotation/tags/tag/text()"))
        self.assertTrue('mytag', 'tag2new' in doc.xpath("/iri/text-annotation/tags/tag/text()"))
        self.assertEqual(doc.xpath("/iri/text-annotation/meta/modified/text()")[0][:11], str(datetime.datetime.now())[:11])
        self.assertEqual(response.status_code, 200)
        
        self.client.logout()
        access_token.delete()
