Working client registration
This commit is contained in:
parent
c840cb6618
commit
4990b47ce4
@ -105,6 +105,29 @@ class User(Base, UserMixin):
|
|||||||
_log.info('Deleted user "{0}" account'.format(self.username))
|
_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):
|
class MediaEntry(Base, MediaEntryMixin):
|
||||||
"""
|
"""
|
||||||
TODO: Consider fetching the media_files using join
|
TODO: Consider fetching the media_files using join
|
||||||
@ -580,7 +603,7 @@ with_polymorphic(
|
|||||||
[ProcessingNotification, CommentNotification])
|
[ProcessingNotification, CommentNotification])
|
||||||
|
|
||||||
MODELS = [
|
MODELS = [
|
||||||
User, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
|
User, Client, MediaEntry, Tag, MediaTag, MediaComment, Collection, CollectionItem,
|
||||||
MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData,
|
MediaFile, FileKeynames, MediaAttachmentFile, ProcessingMetaData,
|
||||||
Notification, CommentNotification, ProcessingNotification,
|
Notification, CommentNotification, ProcessingNotification,
|
||||||
CommentSubscription]
|
CommentSubscription]
|
||||||
|
@ -14,21 +14,47 @@
|
|||||||
# 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/>.
|
||||||
|
|
||||||
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
|
# possible client types
|
||||||
client_types = ["web", "native"] # currently what pump supports
|
client_types = ["web", "native"] # currently what pump supports
|
||||||
|
|
||||||
|
@csrf_exempt
|
||||||
def client_register(request):
|
def client_register(request):
|
||||||
""" Endpoint for client registration """
|
""" Endpoint for client registration """
|
||||||
if request.method == "POST":
|
data = request.get_data()
|
||||||
# new client registration
|
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)
|
||||||
|
|
||||||
return json_response({"dir":dir(request)})
|
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()
|
||||||
|
|
||||||
# check they haven't given us client_id or client_type, they're only used for updating
|
return json_response(
|
||||||
pass
|
{
|
||||||
|
"client_id":client_id,
|
||||||
elif request.method == "PUT":
|
"client_secret":client_secret,
|
||||||
# updating client
|
"expires_at":expirey,
|
||||||
pass
|
})
|
||||||
|
@ -36,6 +36,7 @@ def get_url_map():
|
|||||||
import mediagoblin.webfinger.routing
|
import mediagoblin.webfinger.routing
|
||||||
import mediagoblin.listings.routing
|
import mediagoblin.listings.routing
|
||||||
import mediagoblin.notifications.routing
|
import mediagoblin.notifications.routing
|
||||||
|
import mediagoblin.federation.routing
|
||||||
|
|
||||||
for route in PluginManager().get_routes():
|
for route in PluginManager().get_routes():
|
||||||
add_route(*route)
|
add_route(*route)
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
# 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 base64
|
||||||
|
import string
|
||||||
import errno
|
import errno
|
||||||
import itsdangerous
|
import itsdangerous
|
||||||
import logging
|
import logging
|
||||||
@ -24,6 +26,9 @@ from mediagoblin import mg_globals
|
|||||||
|
|
||||||
_log = logging.getLogger(__name__)
|
_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.
|
# Use the system (hardware-based) random number generator if it exists.
|
||||||
# -- this optimization is lifted from Django
|
# -- this optimization is lifted from Django
|
||||||
@ -111,3 +116,13 @@ def get_timed_signer_url(namespace):
|
|||||||
assert __itsda_secret is not None
|
assert __itsda_secret is not None
|
||||||
return itsdangerous.URLSafeTimedSerializer(__itsda_secret,
|
return itsdangerous.URLSafeTimedSerializer(__itsda_secret,
|
||||||
salt=namespace)
|
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
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
# 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
|
|
@ -14,6 +14,8 @@
|
|||||||
# 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 json
|
||||||
|
|
||||||
import werkzeug.utils
|
import werkzeug.utils
|
||||||
from werkzeug.wrappers import Response as wz_Response
|
from werkzeug.wrappers import Response as wz_Response
|
||||||
from mediagoblin.tools.template import render_template
|
from mediagoblin.tools.template import render_template
|
||||||
@ -31,7 +33,6 @@ def render_to_response(request, template, context, status=200):
|
|||||||
render_template(request, template, context),
|
render_template(request, template, context),
|
||||||
status=status)
|
status=status)
|
||||||
|
|
||||||
|
|
||||||
def render_error(request, status=500, title=_('Oops!'),
|
def render_error(request, status=500, title=_('Oops!'),
|
||||||
err_msg=_('An error occured')):
|
err_msg=_('An error occured')):
|
||||||
"""Render any error page with a given error code, title and text body
|
"""Render any error page with a given error code, title and text body
|
||||||
@ -44,7 +45,6 @@ def render_error(request, status=500, title=_('Oops!'),
|
|||||||
{'err_code': status, 'title': title, 'err_msg': err_msg}),
|
{'err_code': status, 'title': title, 'err_msg': err_msg}),
|
||||||
status=status)
|
status=status)
|
||||||
|
|
||||||
|
|
||||||
def render_403(request):
|
def render_403(request):
|
||||||
"""Render a standard 403 page"""
|
"""Render a standard 403 page"""
|
||||||
_ = pass_to_ugettext
|
_ = pass_to_ugettext
|
||||||
@ -106,3 +106,26 @@ def redirect_obj(request, obj):
|
|||||||
|
|
||||||
Requires obj to have a .url_for_self method."""
|
Requires obj to have a .url_for_self method."""
|
||||||
return redirect(request, location=obj.url_for_self(request.urlgen))
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user