Repository: readthedocs/readthedocs.org

Issue:
Tastypie needs to upgrade our dependencies to support Python3
If you go to http://localhost:8000/api/v1/project/46162/sync_versions/ while running your instance with Python3 you will get this error:

> 'dict' object has no attribute 'has_key'

I found that we are using `mimetype`, https://github.com/rtfd/readthedocs.org/blob/df8079a18ed9c15e9c85f0646e3e9169e725b310/requirements/pip.txt#L49 and `python-mimeparse` should be used.

We should write a simple test for this, otherwise we will find this out in production :)

Ref: http://django-tastypie.readthedocs.io/en/latest/python3.html#changed-requirements


Discussion:
will api v1 still be supported in the long term?
I will like to work on this issue @humitos 
@humitos @stsewd  
the webpage is not available on my local server @ http://localhost:8000/api/v1/project/46162/sync_versions/  
a screenshot of error page:
![image](https://user-images.githubusercontent.com/23264605/36116277-a8a860c6-105b-11e8-94b4-9d65493ad828.png)

@142ayushkumar that's because that url was just an example, you need to create a project on your local instance and take the id. `http://localhost:8000/api/v1/project/{id}/sync_versions/`. And I believe this endpoint only support POST requests, but I'm not sure.

Thanks for your interest on contributing :)
@stsewd, I am facing some problem in webhook integration on my local instance the same way i followed on my live account and it worked. But on the local server 
![image](https://user-images.githubusercontent.com/23264605/36158003-39beba6a-1101-11e8-8b4e-76cbe71e02a5.png)

And one more thing is that how to run my local instance with python3 
I am getting some error `python3 manage.py runserver`
![image](https://user-images.githubusercontent.com/23264605/36158136-91d48b4e-1101-11e8-9b39-560613b06e1e.png)


@142ayushkumar did you have any problem when building your project? You can check the builds section `/projects/django-kon/builds`. And about your other problem I thinks it's because you only setup your project for python2, please follow the installation steps with a python3 virtualenv.
![image](https://user-images.githubusercontent.com/23264605/36158961-a47ba500-1103-11e8-8364-5f3de99ac97b.png)
Build is sucessful.
@142ayushkumar That isn't a successfully build, it's just triggered. I think you need to setup your build environment (see https://docs.readthedocs.io/en/latest/development/buildenvironments.html), by the way, that guide needs improvement, so probably you may want to read https://github.com/rtfd/readthedocs.org/pull/2692/files too. 
@stsewd, Can you help me with the [configuration part](https://docs.readthedocs.io/en/latest/development/buildenvironments.html#configuration). How to change these configurations?
You need to create a file `readthedocs/settings/local_settings.py` and put there your settings. 

This is my local settings https://gist.github.com/stsewd/1fd3178435397c72c563dc83480dc663, you need to set `DOCKER_IMAGE` to yours.
@stsewd where to save the Dockerfile(as mentioned [here](https://github.com/rtfd/readthedocs.org/pull/2692/files?diff=split#diff-bbaadadacee305c8e9d6825771319cfbR48)) in the readthedocs.org folder or in settings?
@stsewd @humitos 
Also after saving the local settings as you suggested I am getting this error
![image](https://user-images.githubusercontent.com/23264605/36214867-88b3c852-11d0-11e8-9cfd-d1d901fa7e9e.png)

@142ayushkumar in any place you like, the important step here is building the image `docker build -f Dockerfile.user -t readthedocs/build:2.0-modified .` on the same directory where the Docker file is. If you use my local_settings.py, you don't need these lines https://gist.github.com/stsewd/1fd3178435397c72c563dc83480dc663#file-local_settings-py-L18-L26.

@stsewd I am still getting error
Error log when i tried to build image using dockerfile
![image](https://user-images.githubusercontent.com/23264605/36256667-dd5cad8e-1279-11e8-9101-8775acfce710.png)
because i have saved my file named as `Dockerfile` not `Dockerfile.user` but the latter also shows errors

> will api v1 still be supported in the long term?

@stsewd the API v1 is _deprecated_ but people still use it. So, we don't want to add features or support it if this involves too much work, but making this small change to keep the compatibility shouldn't be so complicated and I think it worth the effort.

Anyway, the first step is to write a test that fails with Python3 so at least we are covered and this error doesn't pass silently.
@142ayushkumar you should use `docker build -t readthedocs/build:2.0-modified .`

Also I believe we are populating this issue with irrelevant content, probably is better to make this questions on https://gitter.im/rtfd/readthedocs.org or irc (#readthedocs), I would be glad to help you there if you don't mind.
@stsewd @humitos  I would like to work on this issue..
@sriks123  I think the steps given by @humitos are very clear, just follow them. If anything isn't clear, feel free to ask.
@humitos I was submitting a PR to fix this, but I realize that this endpoint doesn't work at all. the `_sync_versions` and `_delete_versions` were deleted on https://github.com/rtfd/readthedocs.org/commit/d11cc9f2a95054c5be3a53e9b47eb17d684f1d38#diff-aeef6dfbd37b07c9cc73482e8c2fb36eL95

So always return an exception

https://github.com/rtfd/readthedocs.org/blob/393e31ad3a9aafee297df64f1a654ffcda7ef04a/readthedocs/api/base.py#L81-L108

I think that was used internally only, now RTD uses the apiv2 endpoint to sync versions.
Should this endpoint be deleted then?
This code was removed in https://github.com/rtfd/readthedocs.org/pull/4038. We only need to update the `mimeparse` dependency. BUT noted that tastypie already includes this in their requirements https://github.com/django-tastypie/django-tastypie/blob/v0.13.0/requirements.txt (same version that we have 0.13.0)

Also I wanna point this that a found about tastypie and breaks our code when updating to `0.13.2` https://github.com/django-tastypie/django-tastypie/issues/1407
Based on docs I wrote documenting our APIv2, I stated that we'd support APIv1 through at least Jan 2019. If that isn't possible, let me know.
https://docs.readthedocs.io/en/latest/api/v1.html
I don't think this will be a problem when updating django or python, so we can hold till 2019 :grin:, but there are some solutions in the related issue (I'm not really familiar with the Authorization part, so I'm not sure how this will affect our code if we want to apply that fix).
@davidfischer I found that we need to update tastypie to support django 1.10 (#4319), if isn't possible to adapt our code to https://github.com/django-tastypie/django-tastypie/issues/1407 we will need to remove tastypie, I'm not sure what decision will be taken here (keep tastypie to extend the api v1 life or upgrade django).

Resolving patch:
diff --git a/readthedocs/api/base.py b/readthedocs/api/base.py
--- a/readthedocs/api/base.py
+++ b/readthedocs/api/base.py
@@ -12,7 +12,7 @@
 from django.core.cache import cache
 from django.shortcuts import get_object_or_404
 from tastypie import fields
-from tastypie.authorization import DjangoAuthorization
+from tastypie.authorization import DjangoAuthorization, ReadOnlyAuthorization
 from tastypie.constants import ALL, ALL_WITH_RELATIONS
 from tastypie.http import HttpCreated
 from tastypie.resources import ModelResource
@@ -39,7 +39,7 @@ class Meta(object):
         allowed_methods = ['get', 'post', 'put']
         queryset = Project.objects.api()
         authentication = PostAuthentication()
-        authorization = DjangoAuthorization()
+        authorization = ReadOnlyAuthorization()
         excludes = ['path', 'featured', 'programming_language']
         filtering = {
             'users': ALL_WITH_RELATIONS,


Test patch:
diff --git a/readthedocs/rtd_tests/tests/test_api.py b/readthedocs/rtd_tests/tests/test_api.py
--- a/readthedocs/rtd_tests/tests/test_api.py
+++ b/readthedocs/rtd_tests/tests/test_api.py
@@ -418,8 +418,8 @@ def test_get_invalid_raw_log(self):
 class APITests(TestCase):
     fixtures = ['eric.json', 'test_data.json']
 
-    def test_make_project(self):
-        """Test that a superuser can use the API."""
+    def test_cant_make_project(self):
+        """Test that a user can't use the API to create projects."""
         post_data = {
             'name': 'awesome-project',
             'repo': 'https://github.com/ericholscher/django-kong.git',
@@ -430,16 +430,7 @@ def test_make_project(self):
             content_type='application/json',
             HTTP_AUTHORIZATION='Basic %s' % super_auth,
         )
-        self.assertEqual(resp.status_code, 201)
-        self.assertEqual(resp['location'], '/api/v1/project/24/')
-        resp = self.client.get(
-            '/api/v1/project/24/',
-            data={'format': 'json'},
-            HTTP_AUTHORIZATION='Basic %s' % eric_auth,
-        )
-        self.assertEqual(resp.status_code, 200)
-        obj = json.loads(resp.content)
-        self.assertEqual(obj['slug'], 'awesome-project')
+        self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)
 
     def test_user_doesnt_get_full_api_return(self):
         user_normal = get(User, is_staff=False)