-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
340 lines (278 loc) · 11.8 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
import os, sys
sys.dont_write_bytecode = True
from oauth import OAuthSignIn
from pprint import pprint
from config import *
from dbMgr import *
from ui import *
@app.route('/')
def index():
return render_template('login_fb.html')
@app.route('/login')
def login():
return render_template('login_fb.html')
@app.route('/about')
def about():
return render_template('about.html')
@app.route('/curation')
def show_curation():
if current_user.is_authenticated:
return render_template('curation.html')
else:
return redirect(url_for('index'))
@app.route('/cards')
def cards():
return render_template('cards.html')
@app.route('/header')
def header():
return render_template('header_search.html')
@app.route('/spec')
def show_specs():
if devmode:
return render_template('spec_testing.html')
else:
return render_template('spec.html')
@app.route('/v1/spec')
def show_specs_v1():
if devmode:
return render_template('spec_testing.html')
else:
return render_template('spec.html')
@app.route('/profile')
def show_user_profile():
return render_template('profile.html')
@app.route('/user')
def redirectUser():
return redirect(url_for("user"))
@app.route('/support')
def support():
return render_template('support.html')
@app.route('/question')
def redirectQuestion():
return redirect(url_for("question"))
@app.route('/answer/<option>')
def redirectAnswer(option):
return redirect(url_for("answer")) + option
# Handle RESTful API for user services like Registration/Login/Logout/Statistics
class userMgr(Resource):
# Update User (Curator) profile.
def put(self):
print "Input received: {} \n".format(request.json)
if not current_user.is_authenticated:
return {'status':"Couldn't authenticate user."}, 400
if request.json == None:
return {'message': 'No input provided'}, 400
# Update tag for a user
if 'tags' in request.json:
#print request.json["tags"], type(request.json["tags"])
if type(request.json["tags"]) != list:
return {'message': 'Tags type should by list of String'}, 400
tags = []
for tag in request.json['tags']:
t = dbC[dname]["tag"].find_one({'tagname':tag})
if t == None:
message = 'tag with name <{}> does not exist'.format(tag)
return {'message': message}, 400
tags = tags + [t["_id"]]
dbC[dname]["curator"].find_one_and_update({'uid':current_user.email},{'$set': {'tags':tags}})
# Update name of a user
if 'name' in request.json:
#print request.json["name"], type(request.json["name"])
if type(request.json["name"]) != str and type(request.json["name"]) != unicode:
return {'message': 'Name type should by String'}, 400
dbC[dname]["curator"].find_one_and_update({'uid':current_user.email},{'$set': {'name':request.json["name"]}})
# Update rating of a user
if 'rating' in request.json:
#print request.json["name"], type(request.json["name"])
if type(request.json["rating"]) != int:
return {'message': 'Rating type should by integer'}, 400
if request.json["rating"] > 5 or request.json["rating"] < 0:
return {'message': 'Rating should be between 0-5 only'}, 400
dbC[dname]["curator"].find_one_and_update({'uid':current_user.email},{'$set': {'rating':request.json["rating"]}})
u = dbC[dname]["curator"].find_one({'uid':current_user.email},projection={'_id':False})
return {"username":u["uid"],"name":u["name"],"tags":getTags(u),"rating":u["rating"]}
class User(UserMixin, usrdb.Model):
__tablename__ = 'users'
id = usrdb.Column(usrdb.Integer, primary_key=True)
social_id = usrdb.Column(usrdb.String(64), nullable=False, unique=True)
email = usrdb.Column(usrdb.String(64), nullable=True)
name = usrdb.Column(usrdb.String(64), nullable=True)
@lm.user_loader
def load_user(id):
return User.query.get(int(id))
@app.route('/test')
def testingFBAuthentication():
if current_user.is_authenticated:
return jsonify({"params":[current_user.social_id,current_user.email,current_user.name]})
else:
return redirect(url_for('index'))
@app.route('/authorize/<provider>')
def oauth_authorize(provider):
if not current_user.is_anonymous:
return redirect(url_for('index'))
oauth = OAuthSignIn.get_provider(provider)
return oauth.authorize()
@app.route('/callback/<provider>')
def oauth_callback(provider):
if not current_user.is_anonymous:
return redirect(url_for('index'))
oauth = OAuthSignIn.get_provider(provider)
social_id, email, name = oauth.callback()
if social_id is None:
flash('Authentication failed.')
return redirect(url_for('index'))
user = User.query.filter_by(social_id=social_id).first()
if not user:
user = User(social_id=social_id,email=email,name=name)
usrdb.session.add(user)
usrdb.session.commit()
addCurator({"uid":email,"name":name,"tags":[],"rating":5})
login_user(user, True)
return redirect(url_for('index'))
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
# Handle RESTful API for getting/submitting questions
class questMgr(Resource):
# Create questions from dedupe provided pairs
def post(self):
print "Input received: {} \n".format(request.json)
if request.json == None:
return {'message': 'No input provided'}, 400
else:
return createQuestionsFromPairs(request.json)
def get(self):
print "Input received: {} \n".format(request.get_json())
print "Input received: {} \n".format(request.json)
print "Input received: {} \n".format(request.data)
print "Input received: {} \n".format(request.args)
if not current_user.is_authenticated:
return {'status':"Couldn't authenticate user."}, 400
if request.args.get('count') == None:
count = 10
else:
count = int(request.args.get('count'))
if request.args.get('stats') == None:
stats = False
else:
if request.args.get('stats').lower() == 'true':
stats = True
else:
stats = False
qs = getQuestionsForUser(count,stats)
#print qs
return qs
# Handle RESTful API for submitting answer
class ansMgr(Resource):
def put(self):
print "Input received: {} \n".format(request.json)
if not current_user.is_authenticated:
return {'status':"Couldn't authenticate user."}, 400
if request.json == None:
return {'status': 400, 'message': 'No input provided'}
# Input validation
if not 'comment' in request.json:
a_comment = "No Comment Provided"
else:
a_comment = request.json['comment']
if not 'value' in request.json:
return {'message': 'value not provided with ther request'}, 400
if not 'qid' in request.json:
return {'message': 'qid not provided with ther request'}, 400
a_value = request.json['value']
if a_value not in [1,2,3] :
return {'message': 'value should be either 1 (Yes) or 2 (No) or 3 (Not Sure) '}, 400
qid = request.json['qid']
uid = current_user.email
answer = {"value":a_value,"comment":a_comment,"author":uid}
rsp = submitAnswer(qid,answer,uid)
if rsp["status"] == False:
return {'message':rsp["message"]},400
else:
return {'message':rsp["message"]}
# Rest API endpoints (V1)
api.add_resource(userMgr, '/v1/user',endpoint='user')
api.add_resource(questMgr, '/v1/question',endpoint='question')
api.add_resource(ansMgr, '/v1/answer',endpoint='answer')
def createQuestionsFromPairs(jsonData):
bulkOutput = []
for i in range(0,jsonData['count']):
payload = jsonData['payload'][i]
#print "\n Processing payload: ",payload
if not 'uri1' in payload:
return {'message': 'uri1 not provided with the request'}, 400
if not 'uri2' in payload:
return {'message': 'uri2 not provided with the request'}, 400
if not 'dedupe' in payload:
return {'message': 'dedupe not provided with the request'}, 400
uri1 = payload['uri1']
uri2 = payload['uri2']
dedupe = payload['dedupe']
decision = addOrUpdateQuestion(uri1,uri2,dedupe)
#printDatabase("question")
output = {"Value":[],"Comment":[]}
if decision != None:
# Iterate over decision documents and send various comments and actual answer
for aid in decision:
a = dbC[dname]["answer"].find_one({'_id':ObjectId(aid)})
output["Value"] = output["Value"]+[a["value"]]
output["Comment"] = output["Comment"]+[a["comment"]]
bulkOutput = bulkOutput+[output]
else:
bulkOutput = bulkOutput+[output]
return bulkOutput
def getQuestionsForUser(count,stats):
uid = current_user.email
questions = getQuestionsForUID(uid)
if questions != None:
output = []
for question in questions:
if checkURIOrdering(question['uri1'],question['uri2']):
left = dbC[dname]["artists"].find_one({'@id':question['uri1']},projection={'_id':False})
right = dbC[dname]["artists"].find_one({'@id':question['uri2']},projection={'_id':False})
if left == None:
print "Couldn't retrieve entity with URI {} \n".format(question['uri1'])
continue
if right == None:
print "Couldn't retrieve entity with URI {} \n".format(question['uri2'])
continue
else:
left = dbC[dname]["artists"].find_one({'@id':question['uri2']},projection={'_id':False})
right = dbC[dname]["artists"].find_one({'@id':question['uri1']},projection={'_id':False})
if left == None:
print "Couldn't retrieve entity with URI {} \n".format(question['uri2'])
continue
if right == None:
print "Couldn't retrieve entity with URI {} \n".format(question['uri1'])
continue
#print "\nLeft\n ",left
#print "\nRight\n ",right
matches = getMatches(left, right)
#print "\nmatches :\n"
#pprint(matches)
t = getTags(question)
if stats == True:
s = getStats(question)
output += [{'qid': str(question['_id']),"ExactMatch":matches["ExactMatch"],"Unmatched":matches['Unmatched'],"tags":t,"stats":s}]
else:
output += [{'qid': str(question['_id']),"ExactMatch":matches["ExactMatch"],"Unmatched":matches['Unmatched'],"tags":t}]
#print output
#print count
return output[:count]
else:
return {'status':"Couldn't retrieve questions mostly because user not found."}, 400
if __name__ == '__main__':
# usrdb is SQLite database for registered user and session management
if devmode:
usrdb.drop_all()
usrdb.create_all()
else:
usrdb.create_all()
# Initialize mongo db
mongo_init()
# Start the app
if devmode:
app.run(debug=True)
else:
app.run(debug=False)