From c33a34d45964a7e49a5eeeabde0ef4a8132ac591 Mon Sep 17 00:00:00 2001 From: xray7224 Date: Mon, 1 Jul 2013 17:50:39 +0100 Subject: [PATCH] Client registration now supports application/x-www-form-urlencoded now --- mediagoblin/db/models.py | 12 ++-- mediagoblin/federation/views.py | 98 +++++++++++++++++++++------------ mediagoblin/tools/validator.py | 46 ++++++++++++++++ 3 files changed, 118 insertions(+), 38 deletions(-) create mode 100644 mediagoblin/tools/validator.py diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 4c39c025..daee9295 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -119,12 +119,16 @@ class Client(Base): updated = Column(DateTime, nullable=False, default=datetime.datetime.now) # optional stuff - redirect_uri = Column(Unicode, nullable=True) - logo_uri = Column(Unicode, nullable=True) + redirect_uri = Column(JSONEncoded, nullable=True) + logo_url = Column(Unicode, nullable=True) application_name = Column(Unicode, nullable=True) - + contacts = Column(JSONEncoded, nullable=True) + def __repr__(self): - return "".format(self.id) + if self.application_name: + return "".format(self.application_name, self.id) + else: + return "".format(self.id) diff --git a/mediagoblin/federation/views.py b/mediagoblin/federation/views.py index 56bacbb1..743fd142 100644 --- a/mediagoblin/federation/views.py +++ b/mediagoblin/federation/views.py @@ -19,6 +19,7 @@ import json from mediagoblin.meddleware.csrf import csrf_exempt from mediagoblin.tools.response import json_response from mediagoblin.tools.crypto import random_string +from mediagoblin.tools.validator import validate_email, validate_url from mediagoblin.db.models import Client # possible client types @@ -33,12 +34,13 @@ def client_register(request): data = json.loads(data) except ValueError: return json_response({"error":"Could not decode JSON"}) + elif request.content_type == "" or request.content_type == "application/x-www-form-urlencoded": + data = request.form else: return json_response({"error":"Unknown Content-Type"}, status=400) if "type" not in data: return json_response({"error":"No registration type provided"}, status=400) - if "application_type" not in data or data["application_type"] not in client_types: return json_response({"error":"Unknown application_type."}, status=400) @@ -51,27 +53,16 @@ def client_register(request): elif "client_secret" not in data: return json_response({"error":"client_secret is required to update."}, status=400) - client = Client.query.filter_by(id=data["client_id"], secret=data["client_secret"]).all() + client = Client.query.filter_by(id=data["client_id"], secret=data["client_secret"]).first() - if not client: - return json_response({"error":"Unauthorized.", status=403) + if client is None: + return json_response({"error":"Unauthorized."}, status=403) - client.logo_url = data.get("logo_url", client.logo_url) client.application_name = data.get("application_name", client.application_name) + client.application_type = data.get("application_type", client.application_type) app_name = ("application_type", client.application_name) if app_name in client_types: client.application_name = app_name - - client.save() - - expirey = 0 if client.expirey is None else client.expirey - - return json_response( - { - "client_id":client.id, - "client_secret":client.secret, - "expires":expirey, - }) elif client_type == "client_associate": # registering @@ -82,27 +73,66 @@ def client_register(request): elif "client_secret" in data: return json_response({"error":"Only set client_secret for update."}, status=400) - # generate the client_id and client_secret - client_id = random_string(22) # seems to be what pump uses - client_secret = random_string(43) # again, seems to be what pump uses - expirey = 0 # for now, lets not have it expire - expirey_db = None if expirey == 0 else expirey - - # save it - client = Client( - id=client_id, - secret=client_secret, - expirey=expirey_db, - application_type=data["type"], - logo_url=data.get("logo_url", None), - redirect_uri=data.get("redirect_uri", None), - application_type=data["application_type"] - ) + # generate the client_id and client_secret + client_id = random_string(22) # seems to be what pump uses + client_secret = random_string(43) # again, seems to be what pump uses + expirey = 0 # for now, lets not have it expire + expirey_db = None if expirey == 0 else expirey + + # save it + client = Client( + id=client_id, + secret=client_secret, + expirey=expirey_db, + application_type=data["application_type"], + ) + + else: + return json_response({"error":"Invalid registration type"}, status=400) + + logo_url = data.get("logo_url", client.logo_url) + if logo_url is not None and not validate_url(logo_url): + return json_response({"error":"Logo URL {0} is not a valid URL".format(logo_url)}, status=400) + else: + client.logo_url = logo_url + application_name=data.get("application_name", None) + + contacts = data.get("contact", None) + if contacts is not None: + if type(contacts) is not unicode: + return json_response({"error":"contacts must be a string of space-separated email addresses."}, status=400) + + contacts = contacts.split() + for contact in contacts: + if not validate_email(contact): + # not a valid email + return json_response({"error":"Email {0} is not a valid email".format(contact)}, status=400) + + + client.contacts = contacts + + request_uri = data.get("request_uris", None) + if request_uri is not None: + if type(request_uri) is not unicode: + return json_respinse({"error":"redirect_uris must be space-separated URLs."}, status=400) + + request_uri = request_uri.split() + + for uri in request_uri: + if not validate_url(uri): + # not a valid uri + return json_response({"error":"URI {0} is not a valid URI".format(uri)}, status=400) + + client.request_uri = request_uri + + client.save() + expirey = 0 if client.expirey is None else client.expirey + return json_response( { - "client_id":client_id, - "client_secret":client_secret, + "client_id":client.id, + "client_secret":client.secret, "expires_at":expirey, }) diff --git a/mediagoblin/tools/validator.py b/mediagoblin/tools/validator.py new file mode 100644 index 00000000..03598f9c --- /dev/null +++ b/mediagoblin/tools/validator.py @@ -0,0 +1,46 @@ +# 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 . + +from wtforms.validators import Email, URL + +def validate_email(email): + """ + Validates an email + + Returns True if valid and False if invalid + """ + + email_re = Email().regex + result = email_re.match(email) + if result is None: + return False + else: + return result.string + +def validate_url(url): + """ + Validates a url + + Returns True if valid and False if invalid + """ + + url_re = URL().regex + result = url_re.match(url) + if result is None: + return False + else: + return result.string + -- 2.25.1