cffc26d by Anon Ray at 2014-06-10 |
1 |
from flask import Module, jsonify, request, make_response |
|
2 |
from flask import abort, g, json, current_app |
75d3bd6 by Anon Ray at 2014-02-19 |
3 |
|
cffc26d by Anon Ray at 2014-06-10 |
4 |
from swtstore.classes.models import Context, Sweet |
|
5 |
from swtstore.classes.exceptions import AlreadyExistsError, InvalidPayload,\ |
|
6 |
ContextDoNotExist |
|
7 |
from swtstore.classes.utils import urlnorm # normalize URLs |
8fe0bbc by Anon Ray at 2014-05-10 |
8 |
from swtstore.classes.utils.httputils import makeCORSHeaders |
f867edb by Anon Ray at 2014-04-10 |
9 |
from swtstore.classes import oauth |
75d3bd6 by Anon Ray at 2014-02-19 |
10 |
|
|
11 |
|
|
12 |
api = Module(__name__) |
|
13 |
|
d120774 by Anon Ray at 2014-03-08 |
14 |
|
75d3bd6 by Anon Ray at 2014-02-19 |
15 |
# Get a specific sweet |
8fe0bbc by Anon Ray at 2014-05-10 |
16 |
# Update a specific sweet |
|
17 |
@api.route('/sweets/<int:id>', methods=['GET', 'PUT']) |
75d3bd6 by Anon Ray at 2014-02-19 |
18 |
def getSweetById(id): |
8fe0bbc by Anon Ray at 2014-05-10 |
19 |
|
|
20 |
# Get a specific sweet |
|
21 |
if request.method == 'GET': |
75d3bd6 by Anon Ray at 2014-02-19 |
22 |
sweet = Sweet.query.get(id) |
|
23 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
24 |
if sweet is None: |
|
25 |
abort(404) |
|
26 |
|
|
27 |
current_app.logger.debug('getSweetById: %s', sweet) |
|
28 |
return jsonify(sweet.to_dict()) |
|
29 |
|
|
30 |
# Update a specific sweet |
|
31 |
elif request.method == 'PUT': |
|
32 |
payload = request.json |
|
33 |
if payload is None: |
|
34 |
abort(400) |
|
35 |
|
|
36 |
current_app.logger.debug('Update Sweet: recvd payload: %s', payload) |
75d3bd6 by Anon Ray at 2014-02-19 |
37 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
38 |
sweet = Sweet.query.get(id) |
|
39 |
|
|
40 |
if sweet is None: |
|
41 |
abort(404) |
|
42 |
|
|
43 |
current_app.logger.debug('Updating sweet %s with new how: %s ', |
|
44 |
sweet.id, payload) |
|
45 |
|
|
46 |
sweet.update(how=payload) |
|
47 |
|
|
48 |
return jsonify(sweet.to_dict()) |
75d3bd6 by Anon Ray at 2014-02-19 |
49 |
|
d120774 by Anon Ray at 2014-03-08 |
50 |
|
75d3bd6 by Anon Ray at 2014-02-19 |
51 |
# Post a sweet to the sweet store |
|
52 |
@api.route('/sweets', methods=['OPTIONS', 'POST']) |
f867edb by Anon Ray at 2014-04-10 |
53 |
@oauth.require_oauth('email', 'sweet') |
|
54 |
def createSweet(oauth_request): |
75d3bd6 by Anon Ray at 2014-02-19 |
55 |
|
|
56 |
response = make_response() |
|
57 |
|
f867edb by Anon Ray at 2014-04-10 |
58 |
client = oauth_request.client |
|
59 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
60 |
#TODO: make a decorator of CORS request |
|
61 |
response = makeCORSHeaders(response, client.host_url) |
d120774 by Anon Ray at 2014-03-08 |
62 |
|
|
63 |
if request.method == 'OPTIONS': |
|
64 |
response.status_code = 200 |
|
65 |
return response |
|
66 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
67 |
payload = request.json or request.data |
|
68 |
if not payload: |
|
69 |
current_app.logger.error('data not found in payload!') |
cffc26d by Anon Ray at 2014-06-10 |
70 |
g.error = 'data not found in payload!' |
75d3bd6 by Anon Ray at 2014-02-19 |
71 |
abort(400) |
|
72 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
73 |
current_app.logger.debug('new sweet payload recvd.. %s', payload) |
75d3bd6 by Anon Ray at 2014-02-19 |
74 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
75 |
# Get the authenticated user from the oauth request object. |
|
76 |
# Older swtr clients sending `who` in string will be ignored. |
|
77 |
who = oauth_request.user |
75d3bd6 by Anon Ray at 2014-02-19 |
78 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
79 |
try: |
|
80 |
swts = Sweet.createSweets(who, payload) |
cffc26d by Anon Ray at 2014-06-10 |
81 |
except (InvalidPayload, ContextDoNotExist) as e: |
|
82 |
current_app.logger.error('Error creating sweets. Error: %s', e) |
8fe0bbc by Anon Ray at 2014-05-10 |
83 |
abort(400) |
75d3bd6 by Anon Ray at 2014-02-19 |
84 |
|
|
85 |
response.status_code = 200 |
8fe0bbc by Anon Ray at 2014-05-10 |
86 |
response.headers['Content-type'] = 'application/json' |
|
87 |
response.data = json.dumps([i.to_dict() for i in swts]) |
75d3bd6 by Anon Ray at 2014-02-19 |
88 |
return response |
|
89 |
|
|
90 |
|
|
91 |
# The Sweet query API: /sweets/q?who=<>&what=<>&where=<> |
|
92 |
# args: who, what, where |
f867edb by Anon Ray at 2014-04-10 |
93 |
@api.route('/sweets/q', methods=['GET', 'OPTIONS']) |
8fe0bbc by Anon Ray at 2014-05-10 |
94 |
#@oauth.require_oauth('sweet') |
|
95 |
def querySweets(): |
f867edb by Anon Ray at 2014-04-10 |
96 |
|
|
97 |
response = make_response() |
8fe0bbc by Anon Ray at 2014-05-10 |
98 |
origin = request.headers.get('Origin', '*') |
|
99 |
response = makeCORSHeaders(response, origin) |
f867edb by Anon Ray at 2014-04-10 |
100 |
|
|
101 |
if request.method == 'OPTIONS': |
cffc26d by Anon Ray at 2014-06-10 |
102 |
response.status_code = 200 |
f867edb by Anon Ray at 2014-04-10 |
103 |
return response |
d120774 by Anon Ray at 2014-03-08 |
104 |
|
|
105 |
args = request.args |
|
106 |
|
|
107 |
# if no arguments are passed, its an invalid request |
|
108 |
if args is None: |
|
109 |
abort(400) |
|
110 |
|
|
111 |
params = {} |
|
112 |
if args.get('who'): |
|
113 |
params['who'] = args.get('who') |
|
114 |
if args.get('what'): |
8fe0bbc by Anon Ray at 2014-05-10 |
115 |
params['what'] = args.get('what') |
d120774 by Anon Ray at 2014-03-08 |
116 |
if args.get('where'): |
|
117 |
params['where'] = urlnorm(args.get('where')) |
|
118 |
|
|
119 |
# if none of the above parameters are present, its an invalid request |
|
120 |
if len(params) == 0: |
|
121 |
abort(400) |
|
122 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
123 |
current_app.logger.debug('recvd params: %s', params) |
d120774 by Anon Ray at 2014-03-08 |
124 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
125 |
sweets = Sweet.queryByAll(params) |
d120774 by Anon Ray at 2014-03-08 |
126 |
|
|
127 |
if len(sweets) == 0: |
8fe0bbc by Anon Ray at 2014-05-10 |
128 |
current_app.logger.info('No sweets found to satisfy query..') |
d120774 by Anon Ray at 2014-03-08 |
129 |
abort(404) |
|
130 |
|
|
131 |
swts = [i.to_dict() for i in sweets] |
|
132 |
|
|
133 |
response.data = json.dumps(swts) |
|
134 |
response.headers['Content-type'] = 'application/json' |
|
135 |
return response |
|
136 |
|
|
137 |
|
|
138 |
# Get a specific context with its definition; based on name |
|
139 |
@api.route('/contexts/<name>', methods=['GET']) |
|
140 |
def getContextByName(name): |
|
141 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
142 |
context = Context.getByName(name) |
d120774 by Anon Ray at 2014-03-08 |
143 |
if context is None: |
|
144 |
abort(404) |
|
145 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
146 |
current_app.logger.debug('getContextByName : %s', context) |
d120774 by Anon Ray at 2014-03-08 |
147 |
return jsonify(context.to_dict()) |
|
148 |
|
cffc26d by Anon Ray at 2014-06-10 |
149 |
|
d120774 by Anon Ray at 2014-03-08 |
150 |
# Get a specific context with its definition; based on id |
|
151 |
@api.route('/contexts/<int:id>', methods=['GET']) |
|
152 |
def getContextById(id): |
|
153 |
|
|
154 |
context = Context.query.get(id) |
|
155 |
if context is None: |
|
156 |
abort(404) |
|
157 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
158 |
current_app.logger.debug('getContextById response: %s', |
|
159 |
jsonify(context.to_dict()).data) |
|
160 |
|
d120774 by Anon Ray at 2014-03-08 |
161 |
return jsonify(context.to_dict()) |
|
162 |
|
75d3bd6 by Anon Ray at 2014-02-19 |
163 |
|
|
164 |
# Create a new Sweet Context |
f867edb by Anon Ray at 2014-04-10 |
165 |
@oauth.require_oauth('email', 'context') |
d120774 by Anon Ray at 2014-03-08 |
166 |
@api.route('/contexts', methods=['POST']) |
75d3bd6 by Anon Ray at 2014-02-19 |
167 |
def createContext(): |
|
168 |
|
|
169 |
response = make_response() |
|
170 |
|
|
171 |
# try our best to get the data from request object |
|
172 |
if request.json: |
|
173 |
payload = request.json |
|
174 |
elif request.data: |
|
175 |
payload = json.loads(request.data) |
|
176 |
else: |
|
177 |
# if not found send back a 400 |
|
178 |
abort(400) |
|
179 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
180 |
current_app.logger.debug('new context payload recvd.. %s', payload) |
75d3bd6 by Anon Ray at 2014-02-19 |
181 |
|
|
182 |
# if data is invalid send back 400 |
|
183 |
if 'name' not in payload and 'definition' not in payload: |
|
184 |
abort(400) |
|
185 |
|
|
186 |
try: |
|
187 |
new_context = Context(payload['name'], payload['definition']) |
|
188 |
|
|
189 |
except AlreadyExistsError: |
|
190 |
# context with same name exists; send back 400? |
8fe0bbc by Anon Ray at 2014-05-10 |
191 |
current_app.logger.info('Context Already Exists Error') |
75d3bd6 by Anon Ray at 2014-02-19 |
192 |
abort(400) |
|
193 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
194 |
current_app.logger.debug('new context created: %s', new_context) |
|
195 |
|
75d3bd6 by Anon Ray at 2014-02-19 |
196 |
# all ok. save the new context |
cffc26d by Anon Ray at 2014-06-10 |
197 |
new_context.persist() |
75d3bd6 by Anon Ray at 2014-02-19 |
198 |
|
|
199 |
response.status_code = 200 |
|
200 |
return response |
|
201 |
|
f867edb by Anon Ray at 2014-04-10 |
202 |
|
|
203 |
# Send back logged in user data |
|
204 |
@api.route('/users/me', methods=['GET', 'OPTIONS']) |
|
205 |
@oauth.require_oauth('email') |
|
206 |
def getCurrentUser(oauth_request): |
|
207 |
response = make_response() |
8fe0bbc by Anon Ray at 2014-05-10 |
208 |
response = makeCORSHeaders(response, oauth_request.client.host_url) |
f867edb by Anon Ray at 2014-04-10 |
209 |
response.status_code = 200 |
|
210 |
|
|
211 |
if request.method == 'OPTIONS': |
|
212 |
return response |
|
213 |
|
8fe0bbc by Anon Ray at 2014-05-10 |
214 |
response.headers['Content-type'] = 'application/json' |
|
215 |
# We have the user object along with the oauth request. Just return it back |
f867edb by Anon Ray at 2014-04-10 |
216 |
response.data = json.dumps(oauth_request.user.to_dict()) |
|
217 |
return response |