Client registration now supports application/x-www-form-urlencoded now
[mediagoblin.git] / mediagoblin / federation / views.py
CommitLineData
c840cb66 1# GNU MediaGoblin -- federated, autonomous media hosting
2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
4990b47c 17import json
18
19from mediagoblin.meddleware.csrf import csrf_exempt
20from mediagoblin.tools.response import json_response
21from mediagoblin.tools.crypto import random_string
c33a34d4 22from mediagoblin.tools.validator import validate_email, validate_url
4990b47c 23from mediagoblin.db.models import Client
c840cb66 24
25# possible client types
26client_types = ["web", "native"] # currently what pump supports
27
4990b47c 28@csrf_exempt
c840cb66 29def client_register(request):
30 """ Endpoint for client registration """
4990b47c 31 data = request.get_data()
32 if request.content_type == "application/json":
33 try:
34 data = json.loads(data)
35 except ValueError:
36 return json_response({"error":"Could not decode JSON"})
c33a34d4 37 elif request.content_type == "" or request.content_type == "application/x-www-form-urlencoded":
38 data = request.form
4990b47c 39 else:
40 return json_response({"error":"Unknown Content-Type"}, status=400)
c840cb66 41
4990b47c 42 if "type" not in data:
43 return json_response({"error":"No registration type provided"}, status=400)
54fbbf09 44 if "application_type" not in data or data["application_type"] not in client_types:
45 return json_response({"error":"Unknown application_type."}, status=400)
46
47 client_type = data["type"]
48
49 if client_type == "client_update":
50 # updating a client
51 if "client_id" not in data:
52 return json_response({"error":"client_id is required to update."}, status=400)
53 elif "client_secret" not in data:
54 return json_response({"error":"client_secret is required to update."}, status=400)
55
c33a34d4 56 client = Client.query.filter_by(id=data["client_id"], secret=data["client_secret"]).first()
54fbbf09 57
c33a34d4 58 if client is None:
59 return json_response({"error":"Unauthorized."}, status=403)
54fbbf09 60
763e300d 61 client.application_name = data.get("application_name", client.application_name)
c33a34d4 62 client.application_type = data.get("application_type", client.application_type)
763e300d 63 app_name = ("application_type", client.application_name)
64 if app_name in client_types:
65 client.application_name = app_name
763e300d 66
54fbbf09 67 elif client_type == "client_associate":
68 # registering
69 if "client_id" in data:
70 return json_response({"error":"Only set client_id for update."}, status=400)
71 elif "access_token" in data:
72 return json_response({"error":"access_token not needed for registration."}, status=400)
73 elif "client_secret" in data:
74 return json_response({"error":"Only set client_secret for update."}, status=400)
75
c33a34d4 76 # generate the client_id and client_secret
77 client_id = random_string(22) # seems to be what pump uses
78 client_secret = random_string(43) # again, seems to be what pump uses
79 expirey = 0 # for now, lets not have it expire
80 expirey_db = None if expirey == 0 else expirey
81
82 # save it
83 client = Client(
84 id=client_id,
85 secret=client_secret,
86 expirey=expirey_db,
87 application_type=data["application_type"],
88 )
89
90 else:
91 return json_response({"error":"Invalid registration type"}, status=400)
92
93 logo_url = data.get("logo_url", client.logo_url)
94 if logo_url is not None and not validate_url(logo_url):
95 return json_response({"error":"Logo URL {0} is not a valid URL".format(logo_url)}, status=400)
96 else:
97 client.logo_url = logo_url
98 application_name=data.get("application_name", None)
99
100 contacts = data.get("contact", None)
101 if contacts is not None:
102 if type(contacts) is not unicode:
103 return json_response({"error":"contacts must be a string of space-separated email addresses."}, status=400)
104
105 contacts = contacts.split()
106 for contact in contacts:
107 if not validate_email(contact):
108 # not a valid email
109 return json_response({"error":"Email {0} is not a valid email".format(contact)}, status=400)
110
111
112 client.contacts = contacts
113
114 request_uri = data.get("request_uris", None)
115 if request_uri is not None:
116 if type(request_uri) is not unicode:
117 return json_respinse({"error":"redirect_uris must be space-separated URLs."}, status=400)
118
119 request_uri = request_uri.split()
120
121 for uri in request_uri:
122 if not validate_url(uri):
123 # not a valid uri
124 return json_response({"error":"URI {0} is not a valid URI".format(uri)}, status=400)
125
126 client.request_uri = request_uri
127
128
4990b47c 129 client.save()
c840cb66 130
c33a34d4 131 expirey = 0 if client.expirey is None else client.expirey
132
4990b47c 133 return json_response(
134 {
c33a34d4 135 "client_id":client.id,
136 "client_secret":client.secret,
4990b47c 137 "expires_at":expirey,
138 })