Revert "Revert "Import messages in blog views""
[mediagoblin.git] / mediagoblin / oauth / oauth.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 import datetime
17
18 from oauthlib.common import Request
19 from oauthlib.oauth1 import RequestValidator
20
21 from mediagoblin import oauth
22 from mediagoblin.db.models import NonceTimestamp, Client, RequestToken, AccessToken
23
24 class GMGRequestValidator(RequestValidator):
25
26 enforce_ssl = False
27
28 def __init__(self, data=None, *args, **kwargs):
29 self.POST = data
30 super(GMGRequestValidator, self).__init__(*args, **kwargs)
31
32 def check_nonce(self, nonce):
33 """
34 This checks that the nonce given is a valid nonce
35
36 RequestValidator.check_nonce checks that it's between a maximum and
37 minimum length which, not only does pump.io not do this from what
38 I can see but there is nothing in rfc5849 which suggests a maximum or
39 minium length should be required so I'm removing that check
40 """
41 # Check the nonce only contains a subset of the safe characters.
42 return set(nonce) <= self.safe_characters
43
44 def save_request_token(self, token, request):
45 """ Saves request token in db """
46 client_id = self.POST[u"oauth_consumer_key"]
47
48 request_token = RequestToken(
49 token=token["oauth_token"],
50 secret=token["oauth_token_secret"],
51 )
52 request_token.client = client_id
53 if u"oauth_callback" in self.POST:
54 request_token.callback = self.POST[u"oauth_callback"]
55 request_token.save()
56
57 def save_verifier(self, token, verifier, request):
58 """ Saves the oauth request verifier """
59 request_token = RequestToken.query.filter_by(token=token).first()
60 request_token.verifier = verifier["oauth_verifier"]
61 request_token.save()
62
63 def save_access_token(self, token, request):
64 """ Saves access token in db """
65 access_token = AccessToken(
66 token=token["oauth_token"],
67 secret=token["oauth_token_secret"],
68 )
69 access_token.request_token = request.oauth_token
70 request_token = RequestToken.query.filter_by(token=request.oauth_token).first()
71 access_token.actor = request_token.actor
72 access_token.save()
73
74 def get_realms(*args, **kwargs):
75 """ Currently a stub - called when making AccessTokens """
76 return list()
77
78 def validate_timestamp_and_nonce(self, client_key, timestamp,
79 nonce, request, request_token=None,
80 access_token=None):
81 # RFC5849 (OAuth 1.0) section 3.3 says the timestamp is going
82 # to be seconds after the epoch, we need to convert for postgres
83 try:
84 timestamp = datetime.datetime.fromtimestamp(float(timestamp))
85 except ValueError:
86 # Well, the client must have passed up something ridiculous
87 return False
88
89 nc = NonceTimestamp.query.filter_by(timestamp=timestamp, nonce=nonce)
90 nc = nc.first()
91 if nc is None:
92 return True
93
94 return False
95
96 def validate_client_key(self, client_key, request):
97 """ Verifies client exists with id of client_key """
98 client_query = Client.query.filter(Client.id != oauth.DUMMY_CLIENT_ID)
99 client = client_query.filter_by(id=client_key).first()
100 if client is None:
101 return False
102
103 return True
104
105 def validate_verifier(self, token, verifier):
106 """ Verifies the verifier token is correct. """
107 request_token = RequestToken.query.filter_by(token=token).first()
108 if request_token is None:
109 return False
110
111 if request_token.verifier != verifier:
112 return False
113
114 return True
115
116 def validate_access_token(self, client_key, token, request):
117 """ Verifies token exists for client with id of client_key """
118 # Get the client for the request
119 client_query = Client.query.filter(Client.id != oauth.DUMMY_CLIENT_ID)
120 client = client_query.filter_by(id=client_key).first()
121
122 # If the client is invalid then it's invalid
123 if client is None:
124 return False
125
126 # Look up the AccessToken
127 access_token_query = AccessToken.query.filter(
128 AccessToken.token != oauth.DUMMY_ACCESS_TOKEN
129 )
130 access_token = access_token_query.filter_by(token=token).first()
131
132 # If there isn't one - we can't validate.
133 if access_token is None:
134 return False
135
136 # Check that the client matches the on
137 request_token_query = RequestToken.query.filter(
138 RequestToken.token != oauth.DUMMY_REQUEST_TOKEN,
139 RequestToken.token == access_token.request_token
140 )
141 request_token = request_token_query.first()
142
143 if client.id != request_token.client:
144 return False
145
146 return True
147
148 def validate_realms(self, *args, **kwargs):
149 """ Would validate reals however not using these yet. """
150 return True # implement when realms are implemented
151
152
153 def get_client_secret(self, client_key, request):
154 """ Retrives a client secret with from a client with an id of client_key """
155 client = Client.query.filter_by(id=client_key).first()
156 return client.secret
157
158 def get_access_token_secret(self, client_key, token, request):
159 access_token = AccessToken.query.filter_by(token=token).first()
160 return access_token.secret
161
162 @property
163 def dummy_client(self):
164 return oauth.DUMMY_CLIENT_ID
165
166 @property
167 def dummy_request_token(self):
168 return oauth.DUMMY_REQUEST_TOKEN
169
170 @property
171 def dummy_access_token(self):
172 return oauth.DUMMY_ACCESS_TOKEN
173
174 class GMGRequest(Request):
175 """
176 Fills in data to produce a oauth.common.Request object from a
177 werkzeug Request object
178 """
179
180 def __init__(self, request, *args, **kwargs):
181 """
182 :param request: werkzeug request object
183
184 any extra params are passed to oauthlib.common.Request object
185 """
186 kwargs["uri"] = kwargs.get("uri", request.url)
187 kwargs["http_method"] = kwargs.get("http_method", request.method)
188 kwargs["body"] = kwargs.get("body", request.data)
189 kwargs["headers"] = kwargs.get("headers", dict(request.headers))
190
191 super(GMGRequest, self).__init__(*args, **kwargs)