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 |
17 | import json |
18 | |
19 | from mediagoblin.meddleware.csrf import csrf_exempt |
20 | from mediagoblin.tools.response import json_response |
21 | from mediagoblin.tools.crypto import random_string |
c33a34d4 |
22 | from mediagoblin.tools.validator import validate_email, validate_url |
4990b47c |
23 | from mediagoblin.db.models import Client |
c840cb66 |
24 | |
25 | # possible client types |
26 | client_types = ["web", "native"] # currently what pump supports |
27 | |
4990b47c |
28 | @csrf_exempt |
c840cb66 |
29 | def 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 | }) |