From: Jan Szejko Date: Mon, 20 Jun 2016 12:43:04 +0000 (+0200) Subject: Merge branch 'api' into filmowa X-Git-Url: https://git.mdrn.pl/edumed.git/commitdiff_plain/47336ec077dcbae1fc40a01a1054cd28224a1649?hp=97d42b897db361883d790f514ac60b18d5bd14f5 Merge branch 'api' into filmowa --- diff --git a/api/handlers.py b/api/handlers.py new file mode 100644 index 0000000..5746b0c --- /dev/null +++ b/api/handlers.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +import json + +from django.contrib.sites.models import Site +from django.core.urlresolvers import reverse +from django.utils.functional import lazy +from piston.handler import BaseHandler +from piston.utils import rc + +from catalogue.forms import LessonImportForm +from catalogue.models import Lesson + +API_BASE = EDUMED_BASE = MEDIA_BASE = lazy( + lambda: u'https://' + Site.objects.get_current().domain, unicode)() + + +class LessonDetails(object): + """Custom fields used for representing Lessons.""" + + @classmethod + def href(cls, lesson): + """ Returns an URI for a Lesson in the API. """ + return API_BASE + reverse("api_lesson", args=[lesson.slug]) + + @classmethod + def url(cls, lesson): + """ Returns Lesson's URL on the site. """ + return EDUMED_BASE + lesson.get_absolute_url() + + +class LessonDetailHandler(BaseHandler, LessonDetails): + """ Main handler for Lesson objects. + + Responsible for single Lesson details. + """ + allowed_methods = ['GET'] + fields = ['title', 'url'] + + def read(self, request, lesson): + """ Returns details of a lesson, identified by a slug. """ + try: + return Lesson.objects.get(slug=lesson) + except Lesson.DoesNotExist: + return rc.NOT_FOUND + + +class LessonsHandler(LessonDetailHandler): + allowed_methods = ('GET', 'POST') + model = Lesson + fields = ['href', 'title', 'url'] + + def create(self, request, *args, **kwargs): + if not request.user.has_perm('catalogue.add_lesson'): + return rc.FORBIDDEN + + data = json.loads(request.POST.get('data')) + form = LessonImportForm(data) + if form.is_valid(): + form.save() + return rc.CREATED + else: + return rc.NOT_FOUND diff --git a/api/helpers.py b/api/helpers.py new file mode 100644 index 0000000..a40373a --- /dev/null +++ b/api/helpers.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +from piston.resource import Resource + + +class CsrfExemptResource(Resource): + """A Custom Resource that is csrf exempt""" + def __init__(self, handler, authentication=None): + super(CsrfExemptResource, self).__init__(handler, authentication) + self.csrf_exempt = getattr(self.handler, 'csrf_exempt', True) \ No newline at end of file diff --git a/api/templates/oauth/challenge.html b/api/templates/oauth/challenge.html new file mode 100644 index 0000000..e69de29 diff --git a/api/templates/piston/authorize_token.html b/api/templates/piston/authorize_token.html new file mode 100644 index 0000000..0151b58 --- /dev/null +++ b/api/templates/piston/authorize_token.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block titleextra %}Zezwól na dostęp do Edukacji Medialnej{% endblock %} + +{% block body %} +

Zezwól na dostęp do Edukacji Medialnej

+ +
+

+ Potwierdź dostęp do Edukacji Medialnej jako użytkownik {{ user }}. +

+ +
+ {% csrf_token %} + {{ form.as_p }} + +
+
+{% endblock %} diff --git a/api/urls.py b/api/urls.py new file mode 100644 index 0000000..a111872 --- /dev/null +++ b/api/urls.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from django.conf.urls import patterns, url +from django.views.decorators.csrf import csrf_exempt +from piston.authentication import OAuthAuthentication, oauth_access_token +from piston.resource import Resource + +from api import handlers +from api.helpers import CsrfExemptResource + +auth = OAuthAuthentication(realm="Edukacja Medialna") + +lesson_list_resource = CsrfExemptResource(handler=handlers.LessonsHandler, authentication=auth) +lesson_resource = Resource(handler=handlers.LessonDetailHandler) + +urlpatterns = patterns( + 'piston.authentication', + url(r'^oauth/request_token/$', 'oauth_request_token'), + url(r'^oauth/authorize/$', 'oauth_user_auth'), + url(r'^oauth/access_token/$', csrf_exempt(oauth_access_token)), +) + +urlpatterns += patterns( + '', + # url(r'^$', TemplateView.as_view(template_name='api/main.html'), name='api'), + + # objects details + url(r'^lessons/(?P[a-z0-9-]+)/$', lesson_resource, name="api_lesson"), + + # lessons + url(r'^lessons/$', lesson_list_resource, name='api_lesson_list'), +) diff --git a/catalogue/forms.py b/catalogue/forms.py new file mode 100644 index 0000000..84f2e43 --- /dev/null +++ b/catalogue/forms.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +from django.forms import Form, CharField + +from librarian import IOFile +from catalogue.models import Lesson + + +class LessonImportForm(Form): + lesson_xml = CharField() + + def save(self, commit=True, **kwargs): + return Lesson.publish(IOFile.from_string(self.cleaned_data['lesson_xml'])) diff --git a/contact/templates/contact/form.html b/contact/templates/contact/form.html index a9741f1..584629a 100644 --- a/contact/templates/contact/form.html +++ b/contact/templates/contact/form.html @@ -1,5 +1,6 @@ {% extends form.base_template|default:"base.html" %} {% load chunks %} +{% load honeypot %} {% block title %}{{ form.form_title }}{% endblock %} @@ -15,6 +16,7 @@
{% csrf_token %} + {% render_honeypot_field %} {{ form.as_table }} diff --git a/contact/views.py b/contact/views.py index e52b6b2..b9a411f 100644 --- a/contact/views.py +++ b/contact/views.py @@ -5,10 +5,13 @@ from django.contrib.auth.decorators import permission_required from django.http import Http404 from django.shortcuts import get_object_or_404, redirect, render from fnpdjango.utils.views import serve_file +from honeypot.decorators import check_honeypot + from .forms import contact_forms from .models import Attachment +@check_honeypot def form(request, form_tag, force_enabled=False): try: form_class = contact_forms[form_tag] diff --git a/edumed/settings/apps.py b/edumed/settings/apps.py index ca243c9..04835b5 100644 --- a/edumed/settings/apps.py +++ b/edumed/settings/apps.py @@ -27,6 +27,7 @@ INSTALLED_APPS = ( 'django_libravatar', 'sorl.thumbnail', 'subdomains', + 'piston', 'django.contrib.auth', 'django.contrib.contenttypes', diff --git a/edumed/settings/middleware.py b/edumed/settings/middleware.py index 15ab189..3dc3278 100644 --- a/edumed/settings/middleware.py +++ b/edumed/settings/middleware.py @@ -10,7 +10,6 @@ MIDDLEWARE_CLASSES = process_app_deps(( 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', - 'honeypot.middleware.HoneypotMiddleware', ('django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth'), ('django_cas.middleware.CASMiddleware', 'django_cas'), ('django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages'), diff --git a/edumed/urls.py b/edumed/urls.py index a62aee3..a06a2e9 100644 --- a/edumed/urls.py +++ b/edumed/urls.py @@ -24,6 +24,7 @@ urlpatterns = patterns( url(r'^forum/', include('pybb.urls', namespace='pybb')), url(r'^kompetencje/', include('curriculum.urls')), url(r'^wtem/', include('wtem.urls')), + url(r'^api/', include('api.urls')), ) diff --git a/requirements.txt b/requirements.txt index e75d0eb..1daff32 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ django-pipeline>=1.3,<1.4 python-memcached django-piwik django-extensions +django-piston==0.2.2.1.2 #pyScss #git+git://github.com/Kronuz/pyScss.git@d8f4da23a3c87696a75b3830ed4ab49b75550a93#egg=pyScss #TODO: pyScss support, for now just install sass