Finishes most of oauth, just decorator to complete
This commit is contained in:
parent
405aa45adc
commit
2b60a56cbe
@ -22,7 +22,8 @@ from werkzeug.exceptions import Forbidden, NotFound
|
|||||||
from mediagoblin import mg_globals as mgg
|
from mediagoblin import mg_globals as mgg
|
||||||
from mediagoblin import messages
|
from mediagoblin import messages
|
||||||
from mediagoblin.db.models import MediaEntry, User
|
from mediagoblin.db.models import MediaEntry, User
|
||||||
from mediagoblin.tools.response import redirect, render_404
|
from mediagoblin.tools.request import decode_authorization_header
|
||||||
|
from mediagoblin.tools.response import json_response, redirect, render_404
|
||||||
from mediagoblin.tools.translate import pass_to_ugettext as _
|
from mediagoblin.tools.translate import pass_to_ugettext as _
|
||||||
|
|
||||||
|
|
||||||
@ -268,3 +269,16 @@ def auth_enabled(controller):
|
|||||||
return controller(request, *args, **kwargs)
|
return controller(request, *args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
def oauth_requeired(controller):
|
||||||
|
""" Used to wrap API endpoints where oauth is required """
|
||||||
|
@wraps(controller)
|
||||||
|
def wrapper(request, *args, **kwargs):
|
||||||
|
data = request.headers
|
||||||
|
authorization = decode_authorization_header(data)
|
||||||
|
|
||||||
|
if authorization == dict():
|
||||||
|
error = "Missing required parameter."
|
||||||
|
return json_response({"error": error}, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,14 +18,15 @@ import datetime
|
|||||||
|
|
||||||
import oauthlib.common
|
import oauthlib.common
|
||||||
from oauthlib.oauth1 import (AuthorizationEndpoint, RequestValidator,
|
from oauthlib.oauth1 import (AuthorizationEndpoint, RequestValidator,
|
||||||
RequestTokenEndpoint)
|
RequestTokenEndpoint, AccessTokenEndpoint)
|
||||||
|
|
||||||
from mediagoblin.decorators import require_active_login
|
from mediagoblin.decorators import require_active_login
|
||||||
from mediagoblin.tools.translate import pass_to_ugettext
|
from mediagoblin.tools.translate import pass_to_ugettext
|
||||||
from mediagoblin.meddleware.csrf import csrf_exempt
|
from mediagoblin.meddleware.csrf import csrf_exempt
|
||||||
from mediagoblin.tools.request import decode_request
|
from mediagoblin.tools.request import decode_request, decode_authorization_header
|
||||||
from mediagoblin.tools.response import (render_to_response, redirect,
|
from mediagoblin.tools.response import (render_to_response, redirect,
|
||||||
json_response, render_400)
|
json_response, render_400,
|
||||||
|
form_response)
|
||||||
from mediagoblin.tools.crypto import random_string
|
from mediagoblin.tools.crypto import random_string
|
||||||
from mediagoblin.tools.validator import validate_email, validate_url
|
from mediagoblin.tools.validator import validate_email, validate_url
|
||||||
from mediagoblin.db.models import User, Client, RequestToken, AccessToken
|
from mediagoblin.db.models import User, Client, RequestToken, AccessToken
|
||||||
@ -184,7 +185,7 @@ class GMGRequestValidator(RequestValidator):
|
|||||||
|
|
||||||
def save_request_token(self, token, request):
|
def save_request_token(self, token, request):
|
||||||
""" Saves request token in db """
|
""" Saves request token in db """
|
||||||
client_id = self.POST[u"Authorization"][u"oauth_consumer_key"]
|
client_id = self.POST[u"oauth_consumer_key"]
|
||||||
|
|
||||||
request_token = RequestToken(
|
request_token = RequestToken(
|
||||||
token=token["oauth_token"],
|
token=token["oauth_token"],
|
||||||
@ -200,17 +201,21 @@ class GMGRequestValidator(RequestValidator):
|
|||||||
request_token.verifier = verifier["oauth_verifier"]
|
request_token.verifier = verifier["oauth_verifier"]
|
||||||
request_token.save()
|
request_token.save()
|
||||||
|
|
||||||
|
|
||||||
def save_access_token(self, token, request):
|
def save_access_token(self, token, request):
|
||||||
""" Saves access token in db """
|
""" Saves access token in db """
|
||||||
access_token = AccessToken(
|
access_token = AccessToken(
|
||||||
token=token["oauth_token"],
|
token=token["oauth_token"],
|
||||||
secret=token["oauth_secret"],
|
secret=token["oauth_token_secret"],
|
||||||
)
|
)
|
||||||
access_token.request_token = request.body["oauth_token"]
|
access_token.request_token = request.oauth_token
|
||||||
access_token.user = token["user"].id
|
request_token = RequestToken.query.filter_by(token=request.oauth_token).first()
|
||||||
|
access_token.user = request_token.user
|
||||||
access_token.save()
|
access_token.save()
|
||||||
|
|
||||||
|
def get_realms(*args, **kwargs):
|
||||||
|
""" Currently a stub - called when making AccessTokens """
|
||||||
|
return list()
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def request_token(request):
|
def request_token(request):
|
||||||
""" Returns request token """
|
""" Returns request token """
|
||||||
@ -224,45 +229,32 @@ def request_token(request):
|
|||||||
error = "Unknown Content-Type"
|
error = "Unknown Content-Type"
|
||||||
return json_response({"error": error}, status=400)
|
return json_response({"error": error}, status=400)
|
||||||
|
|
||||||
print data
|
if not data and request.headers:
|
||||||
|
data = request.headers
|
||||||
|
|
||||||
|
data = dict(data) # mutableifying
|
||||||
|
|
||||||
if "Authorization" not in data:
|
authorization = decode_authorization_header(data)
|
||||||
|
|
||||||
|
|
||||||
|
if authorization == dict() or u"oauth_consumer_key" not in authorization:
|
||||||
error = "Missing required parameter."
|
error = "Missing required parameter."
|
||||||
return json_response({"error": error}, status=400)
|
return json_response({"error": error}, status=400)
|
||||||
|
|
||||||
|
|
||||||
# Convert 'Authorization' to a dictionary
|
|
||||||
authorization = {}
|
|
||||||
for item in data["Authorization"].split(","):
|
|
||||||
key, value = item.split("=", 1)
|
|
||||||
authorization[key] = value
|
|
||||||
data[u"Authorization"] = authorization
|
|
||||||
|
|
||||||
if "oauth_consumer_key" not in data[u"Authorization"]:
|
|
||||||
error = "Missing required parameter."
|
|
||||||
return json_respinse({"error": error}, status=400)
|
|
||||||
|
|
||||||
# check the client_id
|
# check the client_id
|
||||||
client_id = data[u"Authorization"][u"oauth_consumer_key"]
|
client_id = authorization[u"oauth_consumer_key"]
|
||||||
client = Client.query.filter_by(id=client_id).first()
|
client = Client.query.filter_by(id=client_id).first()
|
||||||
if client is None:
|
if client is None:
|
||||||
# client_id is invalid
|
# client_id is invalid
|
||||||
error = "Invalid client_id"
|
error = "Invalid client_id"
|
||||||
return json_response({"error": error}, status=400)
|
return json_response({"error": error}, status=400)
|
||||||
|
|
||||||
request_validator = GMGRequestValidator(data)
|
# make request token and return to client
|
||||||
|
request_validator = GMGRequestValidator(authorization)
|
||||||
rv = RequestTokenEndpoint(request_validator)
|
rv = RequestTokenEndpoint(request_validator)
|
||||||
tokens = rv.create_request_token(request, authorization)
|
tokens = rv.create_request_token(request, authorization)
|
||||||
|
|
||||||
tokenized = {}
|
return form_response(tokens)
|
||||||
for t in tokens.split("&"):
|
|
||||||
key, value = t.split("=")
|
|
||||||
tokenized[key] = value
|
|
||||||
|
|
||||||
print "[DEBUG] %s" % tokenized
|
|
||||||
|
|
||||||
# check what encoding to return them in
|
|
||||||
return json_response(tokenized)
|
|
||||||
|
|
||||||
class WTFormData(dict):
|
class WTFormData(dict):
|
||||||
"""
|
"""
|
||||||
@ -375,14 +367,18 @@ def authorize_finish(request):
|
|||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def access_token(request):
|
def access_token(request):
|
||||||
""" Provides an access token based on a valid verifier and request token """
|
""" Provides an access token based on a valid verifier and request token """
|
||||||
try:
|
data = request.headers
|
||||||
data = decode_request(request)
|
|
||||||
except ValueError:
|
parsed_tokens = decode_authorization_header(data)
|
||||||
error = "Could not decode data."
|
|
||||||
|
if parsed_tokens == dict() or "oauth_token" not in parsed_tokens:
|
||||||
|
error = "Missing required parameter."
|
||||||
return json_response({"error": error}, status=400)
|
return json_response({"error": error}, status=400)
|
||||||
|
|
||||||
if data == "":
|
|
||||||
error = "Unknown Content-Type"
|
|
||||||
return json_response({"error": error}, status=400)
|
|
||||||
|
|
||||||
print "debug: %s" % data
|
request.oauth_token = parsed_tokens["oauth_token"]
|
||||||
|
request_validator = GMGRequestValidator(data)
|
||||||
|
av = AccessTokenEndpoint(request_validator)
|
||||||
|
tokens = av.create_access_token(request, {})
|
||||||
|
return form_response(tokens)
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import re
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from mediagoblin.db.models import User
|
from mediagoblin.db.models import User
|
||||||
@ -25,6 +26,9 @@ _log = logging.getLogger(__name__)
|
|||||||
form_encoded = "application/x-www-form-urlencoded"
|
form_encoded = "application/x-www-form-urlencoded"
|
||||||
json_encoded = "application/json"
|
json_encoded = "application/json"
|
||||||
|
|
||||||
|
# Regex for Authorization header
|
||||||
|
auth_header_re = re.compile('(\w+)[:=] ?"?(\w+)"?')
|
||||||
|
|
||||||
def setup_user_in_request(request):
|
def setup_user_in_request(request):
|
||||||
"""
|
"""
|
||||||
Examine a request and tack on a request.user parameter if that's
|
Examine a request and tack on a request.user parameter if that's
|
||||||
@ -53,3 +57,9 @@ def decode_request(request):
|
|||||||
else:
|
else:
|
||||||
data = ""
|
data = ""
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def decode_authorization_header(header):
|
||||||
|
""" Decodes a HTTP Authorization Header to python dictionary """
|
||||||
|
authorization = header.get("Authorization", "")
|
||||||
|
tokens = dict(auth_header_re.findall(authorization))
|
||||||
|
return tokens
|
||||||
|
@ -138,3 +138,22 @@ def json_response(serializable, _disable_cors=False, *args, **kw):
|
|||||||
response.headers.set(key, value)
|
response.headers.set(key, value)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def form_response(data, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Responds using application/x-www-form-urlencoded and returns a werkzeug
|
||||||
|
Response object with the data argument as the body
|
||||||
|
and 'application/x-www-form-urlencoded' as the Content-Type.
|
||||||
|
|
||||||
|
Any extra arguments and keyword arguments are passed to the
|
||||||
|
Response.__init__ method.
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = wz_Response(
|
||||||
|
data,
|
||||||
|
content_type="application/x-www-form-urlencoded",
|
||||||
|
*args,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
Loading…
x
Reference in New Issue
Block a user