\w*)/$', textversion_handler),
+ url(r'^setuser/$', setuser_handler),
+ url(r'^doc/$', documentation),
+)
diff -r b5deb8e32219 -r fc5ed157ebfe src/cm/fixtures/test_content.yaml
--- a/src/cm/fixtures/test_content.yaml Fri Jun 11 11:04:23 2010 +0200
+++ b/src/cm/fixtures/test_content.yaml Fri Jul 09 10:05:29 2010 +0200
@@ -360,6 +360,58 @@
adminkey: "text_adminkey_3"
user: 2
+# text 4
+- model : cm.textversion
+ pk: 4
+ fields:
+ created: "2009-02-13 04:01:12"
+ modified: "2009-02-13 04:01:12"
+ title: 'title 4, public text'
+ format: 'markdown'
+ content: 'aaa bbb ccc ddd eee fff ggg'
+ text: 4
+ mod_posteriori: True
+ key: "textversion_key_4"
+ adminkey: "tv_adminkey_4"
+
+- model : cm.text
+ pk: 4
+ fields:
+ created: "2009-02-13 04:01:12"
+ modified: "2009-02-13 04:01:12"
+ last_text_version: 4
+ title: 'title 4, public text'
+ state: "approved"
+ key: "text_key_4"
+ adminkey: "text_adminkey_4"
+ user: 1
+
+# text 5
+- model : cm.textversion
+ pk: 5
+ fields:
+ created: "2009-02-13 04:01:12"
+ modified: "2009-02-13 04:01:12"
+ title: 'title 5, public text'
+ format: 'markdown'
+ content: 'aaa bbb ccc ddd eee fff ggg'
+ text: 5
+ mod_posteriori: True
+ key: "textversion_key_5"
+ adminkey: "tv_adminkey_5"
+
+- model : cm.text
+ pk: 5
+ fields:
+ created: "2009-02-13 04:01:12"
+ modified: "2009-02-13 04:01:12"
+ last_text_version: 5
+ title: 'title 5, public text'
+ state: "approved"
+ key: "text_key_5"
+ adminkey: "text_adminkey_5"
+ user: 1
+
############### userrole ###############
# user 1 is global Manager
@@ -426,6 +478,24 @@
user: 4
text: 2
+# user null (anon is Commentator on text 4)
+# userrole 8
+- model : cm.userrole
+ pk: 8
+ fields:
+ role: 4
+ user: null
+ text: 4
+
+# user null (anon is Commentator on text 5)
+# userrole 9
+- model : cm.userrole
+ pk: 9
+ fields:
+ role: 4
+ user: null
+ text: 5
+
############### comment ###############
# comment 1 (visible on text 2)
diff -r b5deb8e32219 -r fc5ed157ebfe src/cm/security.py
--- a/src/cm/security.py Fri Jun 11 11:04:23 2010 +0200
+++ b/src/cm/security.py Fri Jul 09 10:05:29 2010 +0200
@@ -7,7 +7,7 @@
from django.http import HttpResponseRedirect
from django.utils.http import urlquote
from django.db.models import Q
-
+from piston.utils import rc
import logging
from cm.models import *
@@ -210,8 +210,14 @@
return _check_global_perm
return _dec
+
+def has_perm_on_text_api(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME):
+ return _has_perm_on_text(perm_name, must_be_logged_in, redirect_field_name, api=True)
-def has_perm_on_text(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME):
+def has_perm_on_text(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME, api=False):
+ return _has_perm_on_text(perm_name, must_be_logged_in, redirect_field_name, api)
+
+def _has_perm_on_text(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME, api=False):
"""
decorator protection checking for perm for logged in user
force logged in (i.e. redirect to connection screen if not if must_be_logged_in
@@ -222,15 +228,24 @@
return view_func(request, *args, **kwargs)
if must_be_logged_in and not is_authenticated(request):
- login_url = reverse('login')
- return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, urlquote(request.get_full_path())))
+ if not api:
+ login_url = reverse('login')
+ return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, urlquote(request.get_full_path())))
+ else:
+ return rc.FORBIDDEN
+
if 'key' in kwargs:
text = get_object_or_404(Text, key=kwargs['key'])
else:
raise Exception('no security check possible')
-
- if has_perm(request, perm_name, text=text):
+
+ # in api, the view has an object as first parameter, request is args[0]
+ if not api:
+ req = request
+ else:
+ req = args[0]
+ if has_perm(req, perm_name, text=text):
return view_func(request, *args, **kwargs)
#else:
# TODO: (? useful ?) if some user have the perm and not logged-in : redirect to login
@@ -238,7 +253,11 @@
# return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, urlquote(request.get_full_path())))
# else : unauthorized
- raise UnauthorizedException('No perm %s' % perm_name)
+ if not api:
+ raise UnauthorizedException('No perm %s' % perm_name)
+ else:
+ return rc.FORBIDDEN
+
_check_local_perm.__doc__ = view_func.__doc__
_check_local_perm.__dict__ = view_func.__dict__
diff -r b5deb8e32219 -r fc5ed157ebfe src/cm/templates/api_doc.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/templates/api_doc.html Fri Jul 09 10:05:29 2010 +0200
@@ -0,0 +1,75 @@
+{% extends "site/layout/base_workspace.html" %}
+{% load com %}
+{% load i18n %}
+
+{% block title %}
+{% blocktrans %}API Documentation{% endblocktrans %}
+{% endblock %}
+
+{% block head %}
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+API Documentation
+
+Presentation
+
+The API exposes method for external application to deal with content store in COMT.
+
+The authentification is done using HTTP Authentification.
+
+The default return format is 'json', add '?format=other_format' where other_format is 'json', 'xml', 'yaml' to change the results' format.
+{% load markup %}
+
+ {% regroup docs by type as grouped_docs %}
+
+
+ {% for dd in grouped_docs %}
+ {{ dd.grouper }}
+ {% for doc in dd.list %}
+ {% if not doc.handler.no_display %}
+ {{ doc.handler.title }} ΒΆ
+
+ {{ doc.handler.desc }}
+
+ {{ doc.doc|default:""|restructuredtext }}
+
+
+
+ Endpoint: {{ doc.handler.endpoint }}
+
+
+
+ Method: {% for meth in doc.allowed_methods %}{{ meth }}{% if not forloop.last %}, {% endif %}{% endfor %}
+
+
+
+ Args: {% if doc.handler.args %}{{ doc.handler.args|safe }}{% else %}None{% endif %}
+
+
+
+
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+