I fixed the above problem with URL reversing by refactoring the
JSONRPCService.__call__ method to grab it from the request object.

    def __call__(self, request, extra=None):

        if request.method == "POST":
            return HttpResponse(self.process(request),
                mimetype="application/javascript")

        url = request.get_full_path()
        return HttpResponse(self.get_smd(url),
            mimetype="application/javascript")

This makes more sense since the service url was already defined in the
urlconf, so there's no point in redefining it just so that it can go
in the SMD.

I also reworked the get_smd() method in JSONRPCServiceBase to take the
url parameter:

    def get_smd(self, url):

        smd = {
            "serviceType": "JSON-RPC",
            "serviceURL": url,
            "methods": []
        }

        import inspect
        for method in self.listmethods():
            sig = inspect.getargspec(self.methods[method])
            smd["methods"].append({
                "name": method,
                "parameters": [ {"name": val} for val in sig.args if \
                    val not in ("self", "request") ]
            })

        return simplejson.dumps(smd)

It now defines the smd directly rather than it being defined in
__init__ then populated here.  I also added a test to remove 'self'
and 'request' from the reported method parameters since those are
internal and having them reported will cause an RPC client that
imports the remote methods into their namespace (as was discussed in
previous post) to throw errors.

Purely for my own needs, I added an optional param to
JSONRPCServiceBase.__init__:

def __init__(self, auth_method=None)
    self.auth_method = auth_method

in JSONRPCServiceBase I fixed up process() to call the auth_method (if
it was defined) to determine if the remote client is allowed to call
that method:

    def process(self, request):

        data = simplejson.loads(request.raw_post_data)
        id, method, params = data["id"], data["method"], data
["params"]

        if self.auth_method:
            answer = self.auth_method(request, method, params)
            try:
                answer, message = answer
            except TypeError:
                message = "not authorized"

            if not answer:
                return self.error(id, 100, message)

...

You can use it like so:

def adminrpc_auth(request, method, params):

    return request.session.user.is_admin

adminrpc = JSONRPCService(auth_method=adminrpc_auth)

@jsonremote(adminrpc)
def save_realm(request, realm_obj):

    return realm_obj

This way if you have a collection of methods that should only be
available to an admin user, you can test that in one place rather than
in every method.  The auth_method can optionally return a custom error
message:

return request.session.user.is_admin, "Admins Only"

The default is just "not authorized" -- I'll post my complete mods on
the wiki later.

Any opinions on my modifications are welcome!

Thanks,

Ben
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to