Christopher Allan Webber 76a8e720e5 Merge branch 'stable'
2015-12-20 09:05:00 -06:00

192 lines
6.9 KiB
Python

# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
from oauthlib.common import Request
from oauthlib.oauth1 import RequestValidator
from mediagoblin import oauth
from mediagoblin.db.models import NonceTimestamp, Client, RequestToken, AccessToken
class GMGRequestValidator(RequestValidator):
enforce_ssl = False
def __init__(self, data=None, *args, **kwargs):
self.POST = data
super(GMGRequestValidator, self).__init__(*args, **kwargs)
def check_nonce(self, nonce):
"""
This checks that the nonce given is a valid nonce
RequestValidator.check_nonce checks that it's between a maximum and
minimum length which, not only does pump.io not do this from what
I can see but there is nothing in rfc5849 which suggests a maximum or
minium length should be required so I'm removing that check
"""
# Check the nonce only contains a subset of the safe characters.
return set(nonce) <= self.safe_characters
def save_request_token(self, token, request):
""" Saves request token in db """
client_id = self.POST[u"oauth_consumer_key"]
request_token = RequestToken(
token=token["oauth_token"],
secret=token["oauth_token_secret"],
)
request_token.client = client_id
if u"oauth_callback" in self.POST:
request_token.callback = self.POST[u"oauth_callback"]
request_token.save()
def save_verifier(self, token, verifier, request):
""" Saves the oauth request verifier """
request_token = RequestToken.query.filter_by(token=token).first()
request_token.verifier = verifier["oauth_verifier"]
request_token.save()
def save_access_token(self, token, request):
""" Saves access token in db """
access_token = AccessToken(
token=token["oauth_token"],
secret=token["oauth_token_secret"],
)
access_token.request_token = request.oauth_token
request_token = RequestToken.query.filter_by(token=request.oauth_token).first()
access_token.actor = request_token.actor
access_token.save()
def get_realms(*args, **kwargs):
""" Currently a stub - called when making AccessTokens """
return list()
def validate_timestamp_and_nonce(self, client_key, timestamp,
nonce, request, request_token=None,
access_token=None):
# RFC5849 (OAuth 1.0) section 3.3 says the timestamp is going
# to be seconds after the epoch, we need to convert for postgres
try:
timestamp = datetime.datetime.fromtimestamp(float(timestamp))
except ValueError:
# Well, the client must have passed up something ridiculous
return False
nc = NonceTimestamp.query.filter_by(timestamp=timestamp, nonce=nonce)
nc = nc.first()
if nc is None:
return True
return False
def validate_client_key(self, client_key, request):
""" Verifies client exists with id of client_key """
client_query = Client.query.filter(Client.id != oauth.DUMMY_CLIENT_ID)
client = client_query.filter_by(id=client_key).first()
if client is None:
return False
return True
def validate_verifier(self, token, verifier):
""" Verifies the verifier token is correct. """
request_token = RequestToken.query.filter_by(token=token).first()
if request_token is None:
return False
if request_token.verifier != verifier:
return False
return True
def validate_access_token(self, client_key, token, request):
""" Verifies token exists for client with id of client_key """
# Get the client for the request
client_query = Client.query.filter(Client.id != oauth.DUMMY_CLIENT_ID)
client = client_query.filter_by(id=client_key).first()
# If the client is invalid then it's invalid
if client is None:
return False
# Look up the AccessToken
access_token_query = AccessToken.query.filter(
AccessToken.token != oauth.DUMMY_ACCESS_TOKEN
)
access_token = access_token_query.filter_by(token=token).first()
# If there isn't one - we can't validate.
if access_token is None:
return False
# Check that the client matches the on
request_token_query = RequestToken.query.filter(
RequestToken.token != oauth.DUMMY_REQUEST_TOKEN,
RequestToken.token == access_token.request_token
)
request_token = request_token_query.first()
if client.id != request_token.client:
return False
return True
def validate_realms(self, *args, **kwargs):
""" Would validate reals however not using these yet. """
return True # implement when realms are implemented
def get_client_secret(self, client_key, request):
""" Retrives a client secret with from a client with an id of client_key """
client = Client.query.filter_by(id=client_key).first()
return client.secret
def get_access_token_secret(self, client_key, token, request):
access_token = AccessToken.query.filter_by(token=token).first()
return access_token.secret
@property
def dummy_client(self):
return oauth.DUMMY_CLIENT_ID
@property
def dummy_request_token(self):
return oauth.DUMMY_REQUEST_TOKEN
@property
def dummy_access_token(self):
return oauth.DUMMY_ACCESS_TOKEN
class GMGRequest(Request):
"""
Fills in data to produce a oauth.common.Request object from a
werkzeug Request object
"""
def __init__(self, request, *args, **kwargs):
"""
:param request: werkzeug request object
any extra params are passed to oauthlib.common.Request object
"""
kwargs["uri"] = kwargs.get("uri", request.url)
kwargs["http_method"] = kwargs.get("http_method", request.method)
kwargs["body"] = kwargs.get("body", request.data)
kwargs["headers"] = kwargs.get("headers", dict(request.headers))
super(GMGRequest, self).__init__(*args, **kwargs)