_log.info('Deleted user "{0}" account'.format(self.username))
+class Client(Base):
+ """
+ Model representing a client - Used for API Auth
+ """
+ __tablename__ = "core__clients"
+
+ id = Column(Unicode, nullable=True, primary_key=True)
+ secret = Column(Unicode, nullable=False)
+ expirey = Column(DateTime, nullable=True)
+ application_type = Column(Unicode, nullable=False)
+ created = Column(DateTime, nullable=False, default=datetime.datetime.now)
+ updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
+
+ # optional stuff
+ redirect_uri = Column(Unicode, nullable=True)
+ logo_uri = Column(Unicode, nullable=True)
+ application_name = Column(Unicode, nullable=True)
+
+ def __repr__(self):
+ return "<Client {0}>".format(self.id)
+
+
+
class MediaEntry(Base, MediaEntryMixin):
"""
TODO: Consider fetching the media_files using join
[ProcessingNotification, CommentNotification])
MODELS = [
- User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
+ User, Client, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData,
Notification, CommentNotification, ProcessingNotification,
CommentSubscription]
# 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/>.
-from mediagoblin.tools.json import json_response
+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.db.models import Client
# possible client types
client_types = ["web", "native"] # currently what pump supports
+@csrf_exempt
def client_register(request):
""" Endpoint for client registration """
- if request.method == "POST":
- # new client registration
-
- return json_response({"dir":dir(request)})
+ data = request.get_data()
+ if request.content_type == "application/json":
+ try:
+ data = json.loads(data)
+ except ValueError:
+ return json_response({"error":"Could not decode JSON"})
+ else:
+ return json_response({"error":"Unknown Content-Type"}, status=400)
- # check they haven't given us client_id or client_type, they're only used for updating
- pass
+ if "type" not in data:
+ return json_response({"error":"No registration type provided"}, 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
+ client = Client(
+ id=client_id,
+ secret=client_secret,
+ expirey=expirey_db,
+ application_type=data["type"]
+ )
+ client.save()
- elif request.method == "PUT":
- # updating client
- pass
+ return json_response(
+ {
+ "client_id":client_id,
+ "client_secret":client_secret,
+ "expires_at":expirey,
+ })
import mediagoblin.webfinger.routing
import mediagoblin.listings.routing
import mediagoblin.notifications.routing
+ import mediagoblin.federation.routing
for route in PluginManager().get_routes():
add_route(*route)
# 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 base64
+import string
import errno
import itsdangerous
import logging
_log = logging.getLogger(__name__)
+# produces base64 alphabet
+alphabet = string.ascii_letters + "-_"
+base = len(alphabet)
# Use the system (hardware-based) random number generator if it exists.
# -- this optimization is lifted from Django
assert __itsda_secret is not None
return itsdangerous.URLSafeTimedSerializer(__itsda_secret,
salt=namespace)
+
+def random_string(length):
+ """ Returns a URL safe base64 encoded crypographically strong string """
+ rstring = ""
+ for i in range(length):
+ n = getrandbits(6) # 6 bytes = 2^6 = 64
+ n = divmod(n, base)[1]
+ rstring += alphabet[n]
+
+ return rstring
+++ /dev/null
-# 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 json
-
-from werkzeug.wrappers import Response
-
-def json_response(serializable, _disable_cors=False, *args, **kw):
- '''
- Serializes a json objects and returns a werkzeug Response object with the
- serialized value as the response body and Content-Type: application/json.
-
- :param serializable: A json-serializable object
-
- Any extra arguments and keyword arguments are passed to the
- Response.__init__ method.
- '''
- response = Response(json.dumps(serializable), *args, content_type='application/json', **kw)
-
- if not _disable_cors:
- cors_headers = {
- 'Access-Control-Allow-Origin': '*',
- 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
- 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'}
- for key, value in cors_headers.iteritems():
- response.headers.set(key, value)
-
- return response
# 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 json
+
import werkzeug.utils
from werkzeug.wrappers import Response as wz_Response
from mediagoblin.tools.template import render_template
render_template(request, template, context),
status=status)
-
def render_error(request, status=500, title=_('Oops!'),
err_msg=_('An error occured')):
"""Render any error page with a given error code, title and text body
{'err_code': status, 'title': title, 'err_msg': err_msg}),
status=status)
-
def render_403(request):
"""Render a standard 403 page"""
_ = pass_to_ugettext
Requires obj to have a .url_for_self method."""
return redirect(request, location=obj.url_for_self(request.urlgen))
+
+def json_response(serializable, _disable_cors=False, *args, **kw):
+ '''
+ Serializes a json objects and returns a werkzeug Response object with the
+ serialized value as the response body and Content-Type: application/json.
+
+ :param serializable: A json-serializable object
+
+ Any extra arguments and keyword arguments are passed to the
+ Response.__init__ method.
+ '''
+
+ response = wz_Response(json.dumps(serializable), *args, content_type='application/json', **kw)
+
+ if not _disable_cors:
+ cors_headers = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
+ 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'}
+ for key, value in cors_headers.iteritems():
+ response.headers.set(key, value)
+
+ return response