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