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