Add base REST provider framework classes
[cascardo/ipsilon.git] / ipsilon / rest / common.py
1 # Copyright (C) 2015  Ipsilon Contributors see COPYING for license
2
3 import cherrypy
4 import json
5 from functools import wraps
6 from ipsilon.util.endpoint import Endpoint
7
8
9 def jsonout(func):
10     """
11     JSON output decorator. Does not handle binary data.
12     """
13     @wraps(func)
14     def wrapper(*args, **kw):
15         value = func(*args, **kw)
16         cherrypy.response.headers["Content-Type"] = \
17             "application/json;charset=utf-8"
18         return json.dumps(value, sort_keys=True, indent=2)
19
20     return wrapper
21
22
23 def rest_error(status=500, message=''):
24     """
25     Create a REST error response.
26
27     The assumption is that the jsonout wrapper will handle converting
28     the response to JSON.
29     """
30     cherrypy.response.status = status
31     cherrypy.response.headers['Content-Type'] = 'application/json'
32     return {'status': status, 'message': message}
33
34
35 class RestPage(Endpoint):
36
37     def __init__(self, *args, **kwargs):
38         super(RestPage, self).__init__(*args, **kwargs)
39         self.default_headers.update({
40             'Cache-Control': 'no-cache, must-revalidate',
41             'Pragma': 'no-cache',
42             'Expires': 'Thu, 01 Dec 1994 16:00:00 GMT',
43         })
44         self.auth_protect = True
45
46
47 class RestPlugins(RestPage):
48     def __init__(self, name, site, parent, facility, ordered=True):
49         super(RestPlugins, self).__init__(site)
50         self._master = parent
51         self.name = name
52         self.title = '%s plugins' % name
53         self.url = '%s/%s' % (parent.url, name)
54         self.facility = facility
55         self.template = None
56         self.order = None
57         parent.add_subtree(name, self)
58
59         for plugin in self._site[facility].available:
60             obj = self._site[facility].available[plugin]
61             if hasattr(obj, 'rest'):
62                 cherrypy.log.error('Rest plugin: %s' % plugin)
63                 obj.rest.mount(self)
64
65     def root_with_msg(self, message=None, message_type=None, changed=None):
66         return None
67
68     def root(self, *args, **kwargs):
69         return self.root_with_msg()
70
71
72 class Rest(RestPage):
73
74     def __init__(self, site, mount):
75         super(Rest, self).__init__(site)
76         self.title = None
77         self.mount = mount
78         self.url = '%s/%s' % (self.basepath, mount)
79         self.menu = [self]
80
81     @jsonout
82     def root(self, *args, **kwargs):
83         return rest_error(404, 'Not Found')
84
85     def add_subtree(self, name, page):
86         self.__dict__[name] = page
87
88     def del_subtree(self, name):
89         del self.__dict__[name]