1
2
3
4
5
6 import re
7 import urlparse
8 try:
9 from urlparse import parse_qsl
10 except ImportError:
11 from cgi import parse_qsl
12
13 from restkit.oauth2 import Consumer, Request, SignatureMethod_HMAC_SHA1,\
14 Token
15
16
17 from restkit import util
18
20 """ validate a consumer agains oauth2.Consumer object """
21 if not isinstance(consumer, Consumer):
22 raise ValueError("Invalid consumer.")
23 return consumer
24
26 """ validate a token agains oauth2.Token object """
27 if token is not None and not isinstance(token, Token):
28 raise ValueError("Invalid token.")
29 return token
30
31
33
35 """
36 Initalize Oauth filter wiht a tupple or list of tupples::
37
38 (path, consumer, token, signaturemethod)
39
40 token and method signature are optionnals. Consumer should be an
41 instance of `oauth2.Consumer`, token an instance of `oauth2.Toke`
42 signature method an instance of `oauth2.SignatureMethod`.
43
44 With a list of tupple, the filter will try to match the path with
45 the rule. It allows you to maintain different authorization per
46 path. A wildcard at the indicate to the filter to match all path
47 behind.
48
49 Example the rule::
50
51 /some/resource/*
52
53 will match :
54
55 /some/resource/other
56 /some/resource/other2
57
58 while the rule `/some/resource` will only match the path
59 `/some/resource`.
60
61
62 """
63
64 if not isinstance(rules, list):
65 self.rules = [rules]
66 else:
67 self.rules = rules
68 self.resources = {}
69 self.matches = []
70 self.parse_rules()
71
73 for rule in self.rules:
74 self.add_rule(rule)
75
77 default_method = SignatureMethod_HMAC_SHA1()
78 if len(rule) == 2:
79
80 r = (validate_consumer(rule[1]), None, default_method)
81 elif len(rule) == 3:
82 r = (validate_consumer(rule[1]), validate_token(rule[2]),
83 default_method)
84 elif len(rule) == 4:
85 r = (validate_consumer(rule[1]), validate_token(rule[2]),
86 rule[3] or default_method)
87 else:
88 raise ValueError("Invalid OAUTH resource.")
89
90 path = rule[0]
91 if path.endswith('*'):
92 re_path = re.compile("%s.*" % path.rsplit('*', 1)[0])
93 else:
94 re_path = re.compile("%s$" % path)
95 self.matches.append(re_path)
96 self.resources[re_path] = r
97
99 path = req.uri.path or "/"
100 for m in self.matches:
101 if m.match(path) is not None:
102 return self.resources[m]
103 return False
104
106 resource = self.on_path(req)
107 if not resource:
108 return
109 consumer, token, method = resource
110
111 headers = dict(req.headers)
112 params = {}
113 form = False
114 if req.body and req.body is not None:
115 ctype = headers.get('Content-Type')
116 if ctype is not None and \
117 ctype.startswith('application/x-www-form-urlencoded'):
118
119 form = True
120 params = dict(parse_qsl(req.body))
121
122
123 params.update(parse_qsl(req.uri.query))
124
125 oauth_req = Request.from_consumer_and_token(consumer, token=token,
126 http_method=req.method, http_url=req.url,
127 parameters=params)
128
129 oauth_req.sign_request(method, consumer, token)
130
131 if form:
132 req.body = oauth_req.to_postdata()
133 elif req.method in ('GET', 'HEAD'):
134 req.url = req.final_url = oauth_req.to_url()
135 req.uri = urlparse.urlparse(req.url)
136 else:
137 oauth_headers = oauth_req.to_header()
138 for k, v in list(oauth_headers.items()):
139 k = util.normalize_name(k)
140 if not isinstance(v, basestring):
141 v = str(v)
142 req.headers.append((k, v))
143