def get(self, dbid, sessid, restype, resid=None): if resid == None: return "You want alist of %s/%s/%s" % (dbid, sessid, restype) else: datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) conn.register([Session]) sessobj = datadb["sessions"].Session.find_one({"_id" : ObjectId(sessid)}) if sessobj == None: return Response("{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405) # TODO: Make sure that resid exists in this session before being obtained from gridfs if restype == "attachments" or restype == "rawfiles": gf = gridfs.GridFS(datadb , restype) fileobj = gf.get(ObjectId(resid)) data = wrap_file(request.environ, fileobj) response = current_app.response_class( data, mimetype=fileobj.content_type, direct_passthrough=True) response.content_length = fileobj.length response.last_modified = fileobj.upload_date response.set_etag(fileobj.md5) response.cache_control.max_age = 0 response.cache_control.s_max_age = 0 response.cache_control.public = True response.headers['Content-Disposition'] = 'attachment; filename=' + fileobj.filename response.make_conditional(request) return response else: return "You want %s from views in %s/%s" % (resid, dbid, sessid)
def login_google(oid_response=None): """Does the login via OpenID. """ GOOGLE_IDENTITY_URL = 'https://www.google.com/accounts/o8/id' if oid.fetch_error(): flash("OpenId Error: " + str(oid.fetch_error()), "error") return redirect('/home') elif not oid_response: return oid.try_login(GOOGLE_IDENTITY_URL, ask_for=['email', 'fullname']) # 'nickname' else: # Check if the user exists conn.register([model.User]) dbobj = conn[current_app.config["CONFIGDB"]] userdoc = dbobj["users"].User.find_one( {'type' : 'google', 'name' : oid_response.email }) if userdoc == None: # Not found, create one userdoc = dbobj["users"].User() userdoc["type"] = 'google' userdoc["name"] = oid_response.email userdoc["label"] = oid_response.fullname userdoc.save() # flash('New user account created', 'info') else: pass # flash('Existing account located', 'info') do_user_login(userdoc) return redirect('/sessions')
def bookmarks(): rules = [] # Compile the rules conn.register([Image, Session, User, Rule, Database]) admindb = conn[current_app.config["CONFIGDB"]] # Assert the user is logged in if 'user' in session: name = session['user']['label'] id = session['user']['id'] userobj = admindb["users"].User.find_one({"_id": ObjectId(id)}) if userobj == None: # If the user is not found then something wrong # Redirect the user to home with error message flash("Invalid login", "error") return redirect(url_for('login.login')) else: # Send the user back to login page # with some message flash("You must be logged in to see that resource", "error") return redirect(url_for('login.login')) #pdb.set_trace() noteArray = [] for noteObj in admindb["views"].find({"User":ObjectId(id), "Type":"UserNote"}): noteData = {"noteid": str(noteObj["_id"]), "imgid": noteObj["ViewerRecords"][0]["Image"]["_id"], "imgdb": noteObj["ViewerRecords"][0]["Image"]["database"], "title": noteObj["Title"]} noteArray.append(noteData); data = {"notes": noteArray} return render_template('notes.html', data=data)
def facebook_authorized(resp=None): if resp is None: flash('Facebook Access denied: reason=%s error=%s' % ( request.args['error_reason'], request.args['error_description'] ), 'error') return redirect(url_for('home')) session['oauth_token'] = (resp['access_token'], '') me = facebook.get('/me') # Check if the user exists conn.register([model.User]) dbobj = conn[current_app.config["CONFIGDB"]] userdoc = dbobj["users"].User.find_one( {'type' : 'facebook', 'name' : me.data['email'] }) if userdoc == None: # Not found, create one userdoc = dbobj["users"].User() userdoc["type"] = 'facebook' userdoc["name"] = me.data['email'] userdoc["label"] = me.data['name'] userdoc.save() flash('New facebook user account created', 'info') else: pass flash('Facebook account exists', 'info') do_user_login(userdoc) return redirect('/sessions')
def delete(self, dbid, sessid, restype, resid=None): if resid == None: return Response("{ \"error \" : \"Deletion of all attachments not implemented Must provide resid\"}" , status=405) else: datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) # TODO: This block of code to common and can be abstrated conn.register([Session]) sessobj = datadb["sessions"].Session.find_one({"_id" : ObjectId(sessid)}) if sessobj == None: return Response("{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405) if restype == "attachments" or restype == "rawfiles": # Remove from the gridfs gf = gridfs.GridFS(datadb , restype) gf.delete(ObjectId(resid)) # Remove the reference from session attachments = [value for value in sessobj["attachments"] if value["ref"] != ObjectId(resid)] # Find the index # Remove that index sessobj["attachments"] = attachments if not "images" in sessobj: sessobj["images"] = [] sessobj.validate() sessobj.save() return Response("{ \"Success \" : \" \"}", status=200) else: return "You want %s from views in %s/%s" % (resid, dbid, sessid)
def get_data_db(self, dbid): conn.register([Database]) admindb = conn[current_app.config["CONFIGDB"]] dbobj = admindb["databases"].Database.find_one({'_id': ObjectId(dbid)}) if dbobj == None: return None # TODO: have an application or module level connection pooling return conn[dbobj["dbname"]]
def get_data_db(self, dbid): conn.register([Database]) admindb = conn[current_app.config["CONFIGDB"]] dbobj = admindb["databases"].Database.find_one({'_id' : ObjectId(dbid)}) if dbobj == None: return None # TODO: have an application or module level connection pooling return conn[dbobj["dbname"]]
def glview(): """ - /glview?view=10239094124&db=507619bb0a3ee10434ae0827 """ #pdb.set_trace() # Check the user is logged in. rules = [] # Compile the rules conn.register([Image, Session, User, Rule, Database]) admindb = conn[current_app.config["CONFIGDB"]] # Assert the user is logged in if 'user' in session: name = session['user']['label'] id = session['user']['id'] userobj = admindb["users"].User.find_one({"_id": ObjectId(id)}) if userobj == None: # If the user is not found then something wrong # Redirect the user to home with error message flash("Invalid login", "error") return redirect(url_for('login.login')) else: # Send the user back to login page # with some message flash("You must be logged in to see that resource", "error") return redirect(url_for('login.login')) # See if editing will be enabled. edit = request.args.get('edit', False) # See if the user is requesting a view or session viewid = request.args.get('view', None) # get all the metadata to display a view in the webgl viewer. ajax = request.args.get('json', None) # get bookmarks. (Legacy) bookmarks = request.args.get('bookmarks', None) # this is the same as the sessions db in the sessions page. # TODO: Store database in the view and do not pass as arg. dbid = request.args.get('db', None) admindb = conn[current_app.config["CONFIGDB"]] dbobj = admindb["databases"].Database.find_one({ "_id" : ObjectId(dbid) }) db = conn[dbobj["dbname"]] conn.register([model.Database]) if viewid : viewobj = db["views"].find_one({"_id" : ObjectId(viewid) }) if ajax: return jsonifyView(db,dbid,viewid,viewobj); if bookmarks: return jsonifyBookmarks(db,dbid,viewid,viewobj); # This will be the only path in the future. Everything else is legacy. if 'type' in viewobj: if viewobj["type"] == "comparison" : return glcomparison(db,dbid,viewid,viewobj) # default return glnote(db,dbid,viewid,viewobj,edit)
def glview(): """ - /glview?view=10239094124&db=507619bb0a3ee10434ae0827 """ #pdb.set_trace() # Check the user is logged in. rules = [] # Compile the rules conn.register([Image, Session, User, Rule, Database]) admindb = conn[current_app.config["CONFIGDB"]] # Assert the user is logged in if 'user' in session: name = session['user']['label'] id = session['user']['id'] userobj = admindb["users"].User.find_one({"_id": ObjectId(id)}) if userobj == None: # If the user is not found then something wrong # Redirect the user to home with error message flash("Invalid login", "error") return redirect(url_for('login.login')) else: # Send the user back to login page # with some message flash("You must be logged in to see that resource", "error") return redirect(url_for('login.login')) # See if editing will be enabled. edit = request.args.get('edit', False) # See if the user is requesting a view or session viewid = request.args.get('view', None) # get all the metadata to display a view in the webgl viewer. ajax = request.args.get('json', None) # get bookmarks. (Legacy) bookmarks = request.args.get('bookmarks', None) # this is the same as the sessions db in the sessions page. # TODO: Store database in the view and do not pass as arg. dbid = request.args.get('db', None) admindb = conn[current_app.config["CONFIGDB"]] dbobj = admindb["databases"].Database.find_one({"_id": ObjectId(dbid)}) db = conn[dbobj["dbname"]] conn.register([model.Database]) if viewid: viewobj = db["views"].find_one({"_id": ObjectId(viewid)}) if ajax: return jsonifyView(db, dbid, viewid, viewobj) if bookmarks: return jsonifyBookmarks(db, dbid, viewid, viewobj) # This will be the only path in the future. Everything else is legacy. if 'type' in viewobj: if viewobj["type"] == "comparison": return glcomparison(db, dbid, viewid, viewobj) # default return glnote(db, dbid, viewid, viewobj, edit)
def get(self, dbid, sessid=None): conn.register([Session, Database]) datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) if sessid == None: sessions = datadb["sessions"].Session.find({}, { 'images': 0, 'views': 0, 'attachments': 0 }) sessionlist = list() for asession in sessions: sessionlist.append(asession) if len(sessionlist) > 0: return jsonify({'sessions': sessionlist}) else: return Response( "{ \"error \" : \"You want You want a list of sessions in %s, but there are no sessions in it \"}" % (dbid), status=405) else: # Get and return a list of sessions from given database # TODO: Filter for the user that is requesting sessobj = datadb["sessions"].find_one({"_id": ObjectId(sessid)}) if sessobj == None: return Response( "{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405) # Dereference the views for aview in sessobj["views"]: viewdetails = datadb["views"].find_one({"_id": aview["ref"]}) viewdetails["image"] = datadb["images"].find_one( {"_id": viewdetails["img"]}, {"thumb": 0}) aview["details"] = viewdetails # Dereference the attachments attachments = [] if "attachments" in sessobj: gfs = GridFS(datadb, "attachments") for anattach in sessobj['attachments']: fileobj = gfs.get(anattach["ref"]) anattach["details"] = ({ 'name': fileobj.name, 'length': fileobj.length }) else: sessobj["attachments"] = [] return jsonify(sessobj)
def post(self, dbid, sessid=None): # Parse the data in json format data = request.json # Unknown request if no parameters if data == None: abort(400) conn.register([Session]) db = self.get_data_db(dbid) if data.has_key("insert"): # Create the database object from the supplied parameters try: newsession = db["sessions"].Session() newsession["label"] = data["insert"]["label"] newsession["images"] = [] newsession.validate() newsession.save() except Exception as inst: # # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : %s}" % str(inst), status=405) return jsonify(newsession) elif data.has_key("modify"): # Resid must be supplied if sessid == None : return Response("{\"error\" : \"No session _id supplied for modification\"}" , status=405) try: # Locate the resource newdb = db["sessions"].Session.find_one({"_id" : ObjectId(sessid)}) if newdb == None: raise Exception(" Resource %s not found" % (sessid)) except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) # Now update try: for akey in data["modify"]: # Presently updating only label is supported if akey <> "label": return Response("{\"error\" : \"Cannot modify %s \"}" % (akey) , status=405) newdb[akey] = data["modify"][akey] newdb.validate() newdb.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) return jsonify(newdb) else: # Only insert and modify commands are supported abort(400)
def attachments(): """ Interface for managing attachments first step is to download attachments Just knowing attachid is not enough. It should belong to the session one has access to - /tile/4e695114587718175c000006/t.jpg searches and returns the image """ # Get variables db = request.args.get('sessdb', None) attachid = request.args.get('attachid', None) sessid = request.args.get('sessid', None) cmd = request.args.get('cmd', "get") if cmd == "get": if(db == None or attachid == None or sessid == None): flash('sessdb, attachid and sessid must all be set', "error") return redirect('/home') pass # TODO: Can we store this information in the session information (or a database information) conn.register([model.Database]) admindb = conn[current_app.config["CONFIGDB"]] try: dbid = ObjectId(db) except: flash('dbid is not a valid id', "error") return redirect('/home') dbobj = admindb["databases"].find_one({"_id" : dbid}) db = conn[dbobj['dbname']] if not model.VerifySessionAccess(model.SEE_SESSION, db, sessid): flash('Forbidden Access ', "error") return redirect('/home') # try: gf = gridfs.GridFS(db , "attachments") fileobj = gf.get(ObjectId(attachid)) # except: # flash('Error locating file', "error") # return redirect('/home') # mostly copied from flask/helpers.py, with # modifications for GridFS data = wrap_file(request.environ, fileobj) response = current_app.response_class( data, mimetype=fileobj.content_type, direct_passthrough=True) response.content_length = fileobj.length response.last_modified = fileobj.upload_date response.set_etag(fileobj.md5) response.cache_control.max_age = 0 response.cache_control.s_max_age = 0 response.cache_control.public = True response.headers['Content-Disposition'] = 'attachment; filename=' + fileobj.filename response.make_conditional(request) return response
def do_user_login(user): """ Accepts a Mongokit document """ conn.register([model.Rule]) admindb = conn[current_app.config["CONFIGDB"]] user.update_last_login() user.save() session['user'] = { 'id': user["_id"], 'label': user["label"], 'email' : user["name"], } session['site_admin'] = False session['last_activity'] = user["last_login"] # Also add the rules information to the session if not (ObjectId(current_app.config["DEMO_RULE"]) in user["rules"]): user["rules"].append(ObjectId(current_app.config["DEMO_RULE"])) user.save() # Loop over the rules accesses = { } for arule in user["rules"]: ruleobj = admindb["rules"].Rule.find_one({"_id" : arule}) if ruleobj == None: flash("Rule not found !! " + str(arule), "error") continue # Create empty DBAccess for that db if not str(ruleobj["db"]) in accesses.keys(): accesses[str(ruleobj["db"])] = DBAccess() if 'db_admin' in ruleobj and ruleobj["db_admin"] == True: accesses[str(ruleobj["db"])].db_admin = True if 'can_see_all' in ruleobj and ruleobj["can_see_all"] == True: accesses[str(ruleobj["db"])].can_see_all = True if 'can_see' in ruleobj: if len(ruleobj["can_see"]) > 0: accesses[str(ruleobj["db"])].can_see.append(ruleobj["can_see"]) if 'site_admin' in ruleobj and ruleobj["site_admin"] == True: session["site_admin"] = True # Insert that information in the session # In future, session may contain only session it, # and this could get into database # For debugging # for adb in accesses.keys(): # flash(adb + ": " + str(accesses[adb]), "info") # # flash("Site admin : " + str(session["site_admin"]), "info") flash('You are successfully logged in.', 'success')
def delete(self, dbid, sessid=None): conn.register([Session, Database]) datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) if sessid == None: return Response("{ \"error \" : \"No session to delete\"}", status=405) else: # TODO: Important, Not all users are allowed to delete sessobj = datadb["sessions"].find_one({"_id": ObjectId(sessid)}) if sessobj <> None: # Delete if empty empty = True if "images" in sessobj: if len(sessobj["images"]) > 0: empty = False if "attachments" in sessobj: if len(sessobj["attachments"]) > 0: empty = False if "attachments" in sessobj: if len(sessobj["attachments"]) > 0: empty = False if not empty: return Response( "{ \"error \" : \"Session %s in db %s not empty\"}" % (sessid, dbid), status=405) else: # Perform the delete try: datadb["sessions"].remove({"_id": ObjectId(sessid)}) print "DELETED from application" except Exception as inst: return Response("{\"error\" : %s}" % str(inst), status=405) # TODO: How to return success? return Response("{}") else: return Response( "{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405)
def login_passwd(): """ Processes login request. Logs the user tryign to login with valid password. follows up with do_user_login """ conn.register([model.User]) admindb = conn[current_app.config["CONFIGDB"]] figure = False if request.form.has_key('figure'): figure = request.form['figure'] user = admindb["users"].User.find_one({ "name": request.form['username'], "type": "passwd" }) if user == None: flash('User not found ' + request.form['username'], "error") return redirect('/login') if not ("password_status" in user): user["password_status"] = "ready" user.save() if user["password_status"] == "new": flash( "Account email confirmation pending. Please use reset password link on the login page if you want confirmation email to be sent again", "error") return redirect('/login') if user["password_status"] == "reset-request": flash( "Account password reset pending. Please use reset password link on the login page if you want password reset email to be sent again", "error") return redirect('/login') # Now password_status == ready ! if user["passwd"] != request.form['passwd']: flash('Authentication error. Password rejected', "error") return redirect('/login') else: do_user_login(user) if figure: return redirect(figure) return redirect(flask.request.form["next"])
def get(self, dbid, sessid=None): conn.register([Session, Database]) datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) if sessid == None: sessions = datadb["sessions"].Session.find({}, {'images':0, 'views':0, 'attachments':0}) sessionlist = list() for asession in sessions: sessionlist.append(asession) if len(sessionlist) > 0: return jsonify({'sessions' : sessionlist}) else: return jsonify({'sessions' : sessionlist, "error" : "You want You want a list of sessions in %s, but there are no sessions in it" %(dbid)}) else: # Get and return a list of sessions from given database # TODO: Filter for the user that is requesting sessobj = datadb["sessions"].find_one({"_id" : ObjectId(sessid)}) if sessobj == None: return Response("{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405) # Dereference the views for aview in sessobj["views"]: viewdetails = datadb["views"].find_one({"_id" : aview["ref"]}) # Viewdetails might not be a view if "img" in viewdetails: viewdetails["image"] = datadb["images"].find_one({"_id" : viewdetails["img"]}, { "thumb" : 0}) else: if "ViewerRecords" in viewdetails: viewdetails["image"] = viewdetails["ViewerRecords"][0]["Image"]["_id"] aview["details"] = viewdetails # Dereference the attachments attachments = [] if "attachments" in sessobj: gfs = GridFS(datadb, "attachments") for anattach in sessobj['attachments']: fileobj = gfs.get(anattach["ref"]) anattach["details"] = ({'name': fileobj.name, 'length' : fileobj.length}) else: sessobj["attachments"] = [] return jsonify(sessobj)
def put(self, resid): # put requires admin access # Get json supplied data = request.json # Check for valid parameters # Check if no parameters if data == None: return Response("{\"error\" : \"No parameters ? \"}", status=405) # See if id matches the resource being modified try: if data["_id"] != resid: raise Exception(1) except: return Response( "{\"error\" : \"_id mismatch with the location in the url \"}", status=405) # Try to see if the data can create valid object conn.register([Database]) # The object should exist dbobj = conn[ current_app.config["CONFIGDB"]]["databases"].Database.find_one( {"_id": ObjectId(resid)}) # Unknown request if no parameters if dbobj == None: return Response( "{\"error\" : \"Resource _id: %s doesnot exist\"}" % (resid), status=403) # Create the database object from the supplied parameters try: dbobj["label"] = data["label"] dbobj["host"] = data["host"] dbobj["dbname"] = data["dbname"] dbobj["copyright"] = data["copyright"] dbobj.validate() dbobj.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : %s}" % str(inst), status=405) return jsonify(dbobj)
def login_passwd(): """ Processes login request. Logs the user tryign to login with valid password. follows up with do_user_login """ conn.register([model.User]) admindb = conn[current_app.config["CONFIGDB"]] figure = False if request.form.has_key('figure') : figure = request.form['figure'] user = admindb["users"].User.find_one({"name" : request.form['username'], "type" : "passwd"}) if user == None: flash('User not found ' + request.form['username'], "error") return redirect('/login') if not ("password_status" in user): user["password_status"] = "ready" user.save() if user["password_status"] == "new" : flash("Account email confirmation pending. Please use reset password link on the login page if you want confirmation email to be sent again", "error") return redirect('/login') if user["password_status"] == "reset-request" : flash("Account password reset pending. Please use reset password link on the login page if you want password reset email to be sent again", "error") return redirect('/login') # Now password_status == ready ! if user["passwd"] != request.form['passwd']: flash('Authentication error. Password rejected', "error") return redirect('/login') else: do_user_login(user) if figure : return redirect(figure) return redirect(flask.request.form["next"])
def put(self, resid): # put requires admin access # Get json supplied data = request.json # Check for valid parameters # Check if no parameters if data == None: return Response("{\"error\" : \"No parameters ? \"}", status=405) # See if id matches the resource being modified try: if data["_id"] != resid: raise Exception(1) except: return Response("{\"error\" : \"_id mismatch with the location in the url \"}", status=405) # Try to see if the data can create valid object conn.register([Database]) # The object should exist dbobj = conn[current_app.config["CONFIGDB"]]["databases"].Database.find_one({"_id" : ObjectId(resid)}) # Unknown request if no parameters if dbobj == None: return Response("{\"error\" : \"Resource _id: %s doesnot exist\"}" % (resid), status=403) # Create the database object from the supplied parameters try: dbobj["label"] = data["label"] dbobj["host"] = data["host"] dbobj["dbname"] = data["dbname"] dbobj["copyright"] = data["copyright"] dbobj.validate() dbobj.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : %s}" % str(inst), status=405) return jsonify(dbobj)
def delete(self, dbid, sessid=None): conn.register([Session, Database]) datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) if sessid == None: return Response("{ \"error \" : \"No session to delete\"}", status=405) else: # TODO: Important, Not all users are allowed to delete sessobj = datadb["sessions"].find_one({"_id" : ObjectId(sessid)}) if sessobj <> None: # Delete if empty empty = True if "images" in sessobj: if len(sessobj["images"]) > 0: empty = False if "attachments" in sessobj: if len(sessobj["attachments"]) > 0: empty = False if "attachments" in sessobj: if len(sessobj["attachments"]) > 0: empty = False if not empty: return Response("{ \"error \" : \"Session %s in db %s not empty\"}" % (sessid, dbid), status=405) else: # Perform the delete try: datadb["sessions"].remove({"_id" : ObjectId(sessid)}) print "DELETED from application" except Exception as inst: return Response("{\"error\" : %s}" % str(inst), status=405) # TODO: How to return success? return Response("{}") else: return Response("{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405)
def login_reset(): """ Asks user for a password and its match. Posts back in the same session. Updates the password state in the currently logged in user User must be logged in already (generally by login.confirm) """ # Start with the currently logged in user if request.method == "GET": # In browser request that user wants to reset the password # Create a token # Send out an email # return flask.render_template('profile.html', name=session["user"]["label"], email=session["user"]["email"]) if request.method == "POST": # In browser request that user wants to reset the password label = flask.request.form["label"] passwd = flask.request.form["passwd"] # Verify that the user is logged in or return if not session.has_key("user"): return flask.Response('{"error" : "User not logged in" }') else: # Chagne the information in the session session["user"]["label"] = label # Locate the record conn.register([model.User]) dbobj = conn[current_app.config["CONFIGDB"]] userdoc = dbobj["users"].User.find_one( {'_id': ObjectId(session["user"]["id"])}) userdoc["passwd"] = passwd userdoc["password_status"] = "ready" userdoc["label"] = label userdoc.validate() userdoc.save() return flask.Response('{"success" : "" }')
def login_confirm(): """ End point after login creation or password reset requests Verifies that the request is legitimate and when in good standing follows up with password reset Logs the user in """ token = bson.ObjectId(request.args["token"]) # Check whether that user exists conn.register([model.User]) admindb = conn[current_app.config["CONFIGDB"]] user = admindb["users"].User.find_one({"token": token}) if user == None: flash("Confirmation link expired or invalid", "error") return redirect('/home') # Remove the token del user["token"] if user["password_status"] == "new": flash( "Success, Your email is confirmed, please continue by setting the password here", "success") elif user["password_status"] == "reset-request": flash( "Success, Your request for password reset is verified , please reset the password here", "success") user["password_status"] = "reset" user.validate() user.save() # Todo: do user login do_user_login(user) return redirect('/login.reset')
def modify(): """ Locates a record based on ID and modifies a particular field to new value """ # Get the parameters id = request.args.get('_id', None) collection = request.args.get('collection', None) fields = json.loads(request.args.get('fields', "{}")) db = request.args.get('db', None) # If not enough information return error if id == None or collection == None or db == None: data = { "error": 1, "message": "_id, collection and database are all required" } return jsonify(data) conn.register([model.Database]) admindb2 = conn[current_app.config["CONFIGDB"]] dbobj = admindb2["databases"].find_one({"_id": ObjectId(db)}) # TODO: Make sure that the caller has access rights for modification col = conn[dbobj["dbname"]][collection] rec = col.find_one({"_id": ObjectId(id)}) if rec == None: data = {"error": 1, "message": "Unable to locate record"} return jsonify(data) updated = False for akey in fields: if akey in rec: col.update({"_id": rec["_id"]}, {"$set": {akey: fields[akey]}}) updated = True # Make sure the obtained record has the field we want to modify and validate data = {'success': 1, 'id': id, 'fields': fields} return jsonify(data)
def tile(): """ - /tile/4e695114587718175c000006/t.jpg searches and returns the image """ # Get variables img = request.args.get('img', None) db = request.args.get('db', None) name = request.args.get('name', None) if not 'user' in session: abort(403) conn.register([model.Database]) admindb = conn[current_app.config["CONFIGDB"]] dbobj = admindb["databases"].find_one({"_id": ObjectId(db)}) imgdb = conn[dbobj['dbname']] colImage = imgdb[img] docImage = colImage.find_one({'name': name}) if docImage == None: abort(403) return Response(str(docImage['file']), mimetype="image/jpeg")
def bookmarks(): rules = [] # Compile the rules conn.register([Image, Session, User, Rule, Database]) admindb = conn[current_app.config["CONFIGDB"]] # Assert the user is logged in if 'user' in session: name = session['user']['label'] id = session['user']['id'] userobj = admindb["users"].User.find_one({"_id": ObjectId(id)}) if userobj == None: # If the user is not found then something wrong # Redirect the user to home with error message flash("Invalid login", "error") return redirect(url_for('login.login')) else: # Send the user back to login page # with some message flash("You must be logged in to see that resource", "error") return redirect(url_for('login.login')) #pdb.set_trace() noteArray = [] for noteObj in admindb["views"].find({ "User": ObjectId(id), "Type": "UserNote" }): noteData = { "noteid": str(noteObj["_id"]), "imgid": noteObj["ViewerRecords"][0]["Image"]["_id"], "imgdb": noteObj["ViewerRecords"][0]["Image"]["database"], "title": noteObj["Title"] } noteArray.append(noteData) data = {"notes": noteArray} return render_template('notes.html', data=data)
def modify(): """ Locates a record based on ID and modifies a particular field to new value """ # Get the parameters id = request.args.get('_id', None) collection = request.args.get('collection', None) fields = json.loads(request.args.get('fields', "{}")) db = request.args.get('db', None) # If not enough information return error if id == None or collection == None or db == None: data = {"error" : 1, "message" : "_id, collection and database are all required"} return jsonify(data) conn.register([model.Database]) admindb2 = conn[current_app.config["CONFIGDB"]] dbobj = admindb2["databases"].find_one({"_id" : ObjectId(db)}) # TODO: Make sure that the caller has access rights for modification col = conn[dbobj["dbname"]][collection] rec = col.find_one({ "_id" : ObjectId(id) }) if rec == None: data = {"error" : 1, "message" : "Unable to locate record"} return jsonify(data) updated = False for akey in fields: if akey in rec: col.update({"_id" : rec["_id"]}, { "$set" : { akey : fields[akey] } }) updated = True # Make sure the obtained record has the field we want to modify and validate data = {'success': 1, 'id' : id, 'fields' : fields} return jsonify(data)
def login_reset(): """ Asks user for a password and its match. Posts back in the same session. Updates the password state in the currently logged in user User must be logged in already (generally by login.confirm) """ # Start with the currently logged in user if request.method == "GET": # In browser request that user wants to reset the password # Create a token # Send out an email # return flask.render_template('profile.html', name=session["user"]["label"], email=session["user"]["email"]) if request.method == "POST": # In browser request that user wants to reset the password label = flask.request.form["label"] passwd = flask.request.form["passwd"] # Verify that the user is logged in or return if not session.has_key("user"): return flask.Response('{"error" : "User not logged in" }') else: # Chagne the information in the session session["user"]["label"] = label # Locate the record conn.register([model.User]) dbobj = conn[current_app.config["CONFIGDB"]] userdoc = dbobj["users"].User.find_one({'_id' : ObjectId(session["user"]["id"])}) userdoc["passwd"] = passwd userdoc["password_status"] = "ready" userdoc["label"] = label userdoc.validate() userdoc.save() return flask.Response('{"success" : "" }')
def login_confirm(): """ End point after login creation or password reset requests Verifies that the request is legitimate and when in good standing follows up with password reset Logs the user in """ token = bson.ObjectId(request.args["token"]) # Check whether that user exists conn.register([model.User]) admindb = conn[current_app.config["CONFIGDB"]] user = admindb["users"].User.find_one({"token" : token}) if user == None: flash("Confirmation link expired or invalid", "error") return redirect('/home') # Remove the token del user["token"] if user["password_status"] == "new": flash("Success, Your email is confirmed, please continue by setting the password here", "success") elif user["password_status"] == "reset-request": flash("Success, Your request for password reset is verified , please reset the password here", "success") user["password_status"] = "reset" user.validate() user.save() # Todo: do user login do_user_login(user) return redirect('/login.reset')
def do_user_login(user): """ Accepts a Mongokit document """ conn.register([model.Rule]) admindb = conn[current_app.config["CONFIGDB"]] user.update_last_login() user.save() session['user'] = { 'id': str(user["_id"]), 'label': user["label"], 'email': user["name"], } session['site_admin'] = False session['last_activity'] = user["last_login"] # Also add the rules information to the session if not (ObjectId(current_app.config["DEMO_RULE"]) in user["rules"]): user["rules"].append(ObjectId(current_app.config["DEMO_RULE"])) user.save() # Loop over the rules accesses = {} if user["type"] == "passwd" and (user["name"].endswith("brown.edu") or user["name"].endswith("kitware.com")): # Here grant the user with the demo_brown rule # flash("You used password login, and you get donut ! ") # ObjectId("529d244959a3aee20f8a00ae") brownrule = ObjectId("529d244959a3aee20f8a00ae") if brownrule in user["rules"]: # flash("You already have the rule") pass else: # flash("Rule must be added") user["rules"].append(ObjectId("529d244959a3aee20f8a00ae")) user.save() for arule in user["rules"]: ruleobj = admindb["rules"].Rule.find_one({"_id": arule}) if ruleobj == None: flash("Rule not found !! " + str(arule), "error") continue # Create empty DBAccess for that db if not str(ruleobj["db"]) in accesses.keys(): accesses[str(ruleobj["db"])] = DBAccess() if 'db_admin' in ruleobj and ruleobj["db_admin"] == True: accesses[str(ruleobj["db"])].db_admin = True if 'can_see_all' in ruleobj and ruleobj["can_see_all"] == True: accesses[str(ruleobj["db"])].can_see_all = True if 'can_see' in ruleobj: if len(ruleobj["can_see"]) > 0: accesses[str(ruleobj["db"])].can_see.append(ruleobj["can_see"]) if 'site_admin' in ruleobj and ruleobj["site_admin"] == True: session["site_admin"] = True # Insert that information in the session # In future, session may contain only session it, # and this could get into database # For debugging # for adb in accesses.keys(): # flash(adb + ": " + str(accesses[adb]), "info") # # flash("Site admin : " + str(session["site_admin"]), "info") flash('You are successfully logged in.', 'success')
def post(self, resid=None): # post requires admin access # Parse the data in json format data = request.json # Unknown request if no parameters if data == None: abort(400) conn.register([Database]) # Only insert command is supported if data.has_key("insert") : # Create the database object from the supplied parameters try: if resid <> None: raise Exception("Trying to create new resource at existing resource") newdb = conn[current_app.config["CONFIGDB"]]["databases"].Database() newdb["label"] = data["insert"]["label"] newdb["host"] = data["insert"]["host"] newdb["dbname"] = data["insert"]["dbname"] newdb["copyright"] = data["insert"]["copyright"] newdb.validate() newdb.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) return jsonify(newdb) elif data.has_key("modify"): # Resid must be supplied if resid == None : return Response("{\"error\" : \"No resource id supplied for modification\"}" , status=405) try: # Locate the resource newdb = conn[current_app.config["CONFIGDB"]]["databases"].Database.find_one({"_id" : ObjectId(resid)}) if newdb == None: raise Exception(" Resource %s not found" % (resid)) except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) # Now update try: for akey in data["modify"]: if akey == "_id": return Response("{\"error\" : \"Cannot modify _id \"}" , status=405) # Update other keys if akey in newdb: newdb[akey] = data["modify"][akey] newdb.validate() newdb.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) return jsonify(newdb) else: # Only insert and modify commands supported so far abort(400)
def login_resetrequest(): """ End point for password reset request Asks user for a valid email and posts back, if the account exists, sends out email for password reset. Follows up with login.signup if an account for that email is not found, or login.confirm if the valid account is found. """ if request.method == "GET": # In browser request that user wants to reset the password return flask.render_template('reset-request.html', message="Please reset the password") if request.method == "POST": # Create a token email = flask.request.form["email"] # Find if an account with that name exists conn.register([model.User]) admindb = conn[current_app.config["CONFIGDB"]] userdoc = admindb["users"].User.find_one({"name" : email, "type" : "passwd"}) if userdoc == None: # user not found return flask.Response('{"error" : "User not found"}') # First reset the password name = userdoc["label"] emailto = userdoc["name"] # Create accout and a random tocken userdoc["token"] = bson.ObjectId() userdoc["password_status"] = "reset-request" # May only be useful for some if "password_ready" in userdoc: del userdoc["password_ready"] userdoc.validate() userdoc.save() # Create email emailfrom = current_app.config["EMAIL_FROM"] body = "Hello " + name + ",\n\n" body = body + "You recently requested a password reset for your account at https://slide-atlas.org." body = body + "\n To complete the request operation please follow the link below- \n" body = body + "\n " + url_for('.login_confirm', _external=True) + "?token=" + str(userdoc["token"]) + " \n" body = body + "\nIf clicking on the link doesn't work, try copying and pasting it into your browser.\n" body = body + "\nThis link will work only once, and will let you create a new password. \n" body = body + "\nIf you did not request password reset, please disregard this message.\n" body = body + "\nThank you,\nThe SlideAtlas Administration Team\n" # Create a text/plain message msg = MIMEText(body) # me == the sender's email address # you == the recipient's email address msg['Subject'] = 'Password reset confirmation for slide-atlas.org' msg['From'] = emailfrom msg['To'] = emailto print msg s = smtplib.SMTP(current_app.config["SMTP"]) try: out = s.sendmail(emailfrom, [emailto], msg.as_string()) except: return flask.Response("{\"error\" : \"Error sending email\"}") s.quit() return flask.Response("{\"success\" : \"" + str(out) + "\"}")
def sessions(): """ - /sessions With no argument displays list of sessions accessible to current user - /sessions?sessid=10239094124 searches for the session id """ rules = [] # Compile the rules conn.register([Image, Session, User, Rule, Database]) admindb = conn[current_app.config["CONFIGDB"]] #pdb.set_trace() # Assert the user is logged in if 'user' in session: name = session['user']['label'] id = session['user']['id'] userobj = admindb["users"].User.find_one({"_id": ObjectId(id)}) if userobj == None: # If the user is not found then something wrong # Redirect the user to home with error message flash("Invalid login", "error") return redirect(url_for('login.login')) else: # Send the user back to login page # with some message flash("You must be logged in to see that resource", "error") return redirect(url_for('login.login')) # This code gets executed only if the user information is available # See if the user is requesting any session id sessid = request.args.get('sessid', None) sessdb = request.args.get('sessdb', "") ajax = request.args.get('json', None) next = int(request.args.get('next', 0)) if sessid : # Find and return image list from single session # TODO: Refactor this into a function db = admindb access = True # eventually sessdb will go away. if sessdb != "" : access = False dbobj = admindb["databases"].Database.find_one({ "_id" : ObjectId(sessdb) }) db = conn[dbobj["dbname"]] # From rules pertaining to current user try: for arule in userobj["rules"]: ruleobj = admindb["rules"].Rule.find_one({"_id" : arule}) if str(ruleobj["db"]) == sessdb: if 'db_admin' in ruleobj and ruleobj["db_admin"] == True: access = True elif 'can_see_all' in ruleobj and ruleobj["can_see_all"] == True: access = True elif len(ruleobj["can_see"]) > 0: for asession in ruleobj["can_see"]: if str(asession) == sessid: access = True except: pass # Confirm that the user has access if access == False : flash("Unauthorized access", "error") return redirect("/home") coll = db["sessions"] asession = coll.find_one({'_id' : ObjectId(sessid)} , {'images':{ '$slice' : [next, NUMBER_ON_PAGE] }, '_id' : 0}) # Hide notes and descriptive title for student review hideAnnotations = False if "hideAnnotations" in asession: if asession["hideAnnotations"] : hideAnnotations = True else : asession["hideAnnotations"] = False # iterate through the session objects images = [] if asession.has_key("views"): for aview in asession['views']: hide = False if 'hide' in aview : if aview["hide"] : hide = True viewobj = db["views"].find_one({"_id" : aview["ref"]}) # Crash here. Session had a viewid that did not exist. # Should we clean up the broken reference? Just skip for now. if viewobj : imgid = 0 imgdb = "" imgobj = None if "Type" in viewobj: # my new notes make it difficult to get the image. if viewobj["Type"] == "Note" : if viewobj["ViewerRecords"][0].has_key("Database") : imgid = viewobj["ViewerRecords"][0]["Image"] imgdb = viewobj["ViewerRecords"][0]["Database"] else : imgid = viewobj["ViewerRecords"][0]["Image"]["_id"] imgdb = viewobj["ViewerRecords"][0]["Image"]["database"] if imgid == 0 : imgdb = sessdb imgid = str(viewobj["img"]) if "imgdb" in viewobj : imgdb = viewobj["imgdb"] if imgdb == sessdb : imgobj = db["images"].find_one({'_id' : ObjectId(imgid)}, {'_id' : 0}) else : dbobj2 = admindb["databases"].Database.find_one({ "_id" : ObjectId(imgdb) }) #TODO: make sure the connection to host is available db2 = conn[dbobj2["dbname"]] imgobj = db2["images"].find_one({'_id' : ObjectId(imgid)}, {'_id' : 0}) # so many legacy schemas (plus hiding annotation) label = "" if "label" in imgobj: label = imgobj["label"] if "label" in aview : label = aview["label"] if "Title" in viewobj : label = viewobj["Title"] if hideAnnotations : label = viewobj["HiddenTitle"] if 'hide' in imgobj : if imgobj["hide"] : hide = True if 'hide' in viewobj : if viewobj["hide"] : hide = True if not hide : if imgobj.has_key("thumb"): del imgobj['thumb'] animage = {} animage['db'] = imgdb animage["img"] = imgid animage["label"] = label animage["view"] = str(aview["ref"]) if "type" in viewobj: if viewobj["type"] == "comparison": animage["comparison"] = 1 images.append(animage) attachments = [] if asession.has_key("attachments"): gfs = GridFS(db, "attachments") for anattach in asession['attachments']: fileobj = gfs.get(anattach["ref"]) attachments.append({'name': fileobj.name, 'id' : anattach["ref"]}) del asession["attachments"] if 'images' in asession: del asession["images"] data = { 'success': 1, 'session' : asession, 'images' : images, 'attachments' :attachments, 'db' : sessdb, 'sessid' : sessid, 'next' : url_for('session.sessions', sessid=sessid, ajax=1, next=next + NUMBER_ON_PAGE) } if ajax: return jsonify(data) else: return render_template('session.html', data=data, name=name) else: # Compile a list of session names / ids sessionlist = [] # sessions owned by this user. rule = {} rule["rule"] = "" sessions = [] for sessionobj in admindb["sessions"].find(): thissession = {'sessid' : str(sessionobj["_id"]), 'label' : sessionobj["label"], 'sessdb': "" } sessions.append(thissession) rule["sessions"] = sessions sessionlist.append(rule) # From rules pertaining to current user if "rules" in userobj: for arule in userobj["rules"]: rule = {} ruleobj = admindb["rules"].Rule.find_one({"_id" : arule}) if ruleobj == None: continue #flash(str(ruleobj), 'success') rule["rule"] = ruleobj["label"] # Find the db pertaining to this rule dbobj = admindb["databases"].Database.find_one({"_id" : ruleobj["db"]}) # TODO: initiate new connection if required with this database db = conn[dbobj["dbname"]] sessions = [] if 'can_see_all' in ruleobj and ruleobj["can_see_all"] == True: #flash("All" + ruleobj["label"], "success") # Gets access to see / admin all sessions in this DB for sessionobj in db["sessions"].Session.find(): thissession = {'sessid' : str(sessionobj["_id"]), 'label' : sessionobj["label"], 'sessdb': str(dbobj["_id"]) } if 'type' in sessionobj: if (sessionobj["type"] == "stack"): thissession["stack"] = True; sessions.append(thissession) elif len(ruleobj["can_see"]) > 0: # Gets access to a limited number of sessions for asession in ruleobj["can_see"]: sessionobj = db["sessions"].Session.find_one({"_id" : asession}) if sessionobj == None: continue thissession = {'sessid' : str(sessionobj["_id"]), 'label' : sessionobj["label"], 'sessdb': str(dbobj["_id"]) } if 'type' in sessionobj: if (sessionobj["type"] == "stack"): thissession["stack"] = True; sessions.append(thissession) # if db administrator if 'db_admin' in ruleobj and ruleobj["db_admin"] == True: # Update the administrative for asession in sessions: #flash("Admin session: " + asession["label"] , "success") asession["canadmin"] = True rule["sessions"] = sessions sessionlist.append(rule) # End of for loop over rules if ajax: return jsonify(sessions=sessionlist, name=name, ajax=1) else: return render_template('sessionlist.html', sessions=sessionlist, name=name)
def login_signup(): """ "Displays the signup template when getting else processes signup request when posting """ if request.method == "POST": name = request.form["name"] emailto = request.form["email"] # Check whether that user exists conn.register([model.User]) admindb = conn[current_app.config["CONFIGDB"]] user = admindb["users"].User.find_one({"name" : emailto, "type" : "passwd"}) if user != None: return flask.Response("{\"error\" : \"User exists\"}") # Create accout and a random tocken token = bson.ObjectId() # Not found, create one userdoc = admindb["users"].User() userdoc["type"] = 'passwd' userdoc["name"] = emailto userdoc["label"] = name userdoc["token"] = token userdoc["password_status"] = "new" userdoc.validate() userdoc.save() # Create email emailfrom = current_app.config["EMAIL_FROM"] body = "Hello " + name + ",\n\n" body = body + "You recently created a new account at https://slide-atlas.org. To proceed with your account creation please follow the link below:\n" body = body + "\n " + url_for('.login_confirm', _external=True) + "?token=" + str(token) + " \n" body = body + "\nIf clicking on the link doesn't work, try copying and pasting it into your browser.\n" body = body + "\nThis link will work only once, and will let you create a new password. \n" body = body + "\nIf you did not enter this address as your contact email, please disregard this message.\n" body = body + "\nThank you,\nThe SlideAtlas Administration Team\n" # Create a text/plain message msg = MIMEText(body) # me == the sender's email address # you == the recipient's email address msg['Subject'] = 'Account email confirmation for slide-atlas.org' msg['From'] = emailfrom msg['To'] = emailto s = smtplib.SMTP(current_app.config["SMTP"]) try: out = s.sendmail(emailfrom, [emailto], msg.as_string()) except: return flask.Response("{\"error\" : \"Error sending email\"}") s.quit() return flask.Response("{\"success\" : \"" + str(out) + "\"}") else: # Only two methods supported return render_template('signup.html')
def do_user_login(user): """ Accepts a Mongokit document """ conn.register([model.Rule]) admindb = conn[current_app.config["CONFIGDB"]] user.update_last_login() user.save() session['user'] = { 'id': str(user["_id"]), 'label': user["label"], 'email' : user["name"], } session['site_admin'] = False session['last_activity'] = user["last_login"] # Also add the rules information to the session if not (ObjectId(current_app.config["DEMO_RULE"]) in user["rules"]): user["rules"].append(ObjectId(current_app.config["DEMO_RULE"])) user.save() # Loop over the rules accesses = { } if user["type"] == "passwd" and (user["name"].endswith("brown.edu") or user["name"].endswith("kitware.com")): # Here grant the user with the demo_brown rule # flash("You used password login, and you get donut ! ") # ObjectId("529d244959a3aee20f8a00ae") brownrule = ObjectId("529d244959a3aee20f8a00ae") if brownrule in user["rules"]: # flash("You already have the rule") pass else: # flash("Rule must be added") user["rules"].append(ObjectId("529d244959a3aee20f8a00ae")) user.save() for arule in user["rules"]: ruleobj = admindb["rules"].Rule.find_one({"_id" : arule}) if ruleobj == None: flash("Rule not found !! " + str(arule), "error") continue # Create empty DBAccess for that db if not str(ruleobj["db"]) in accesses.keys(): accesses[str(ruleobj["db"])] = DBAccess() if 'db_admin' in ruleobj and ruleobj["db_admin"] == True: accesses[str(ruleobj["db"])].db_admin = True if 'can_see_all' in ruleobj and ruleobj["can_see_all"] == True: accesses[str(ruleobj["db"])].can_see_all = True if 'can_see' in ruleobj: if len(ruleobj["can_see"]) > 0: accesses[str(ruleobj["db"])].can_see.append(ruleobj["can_see"]) if 'site_admin' in ruleobj and ruleobj["site_admin"] == True: session["site_admin"] = True # Insert that information in the session # In future, session may contain only session it, # and this could get into database # For debugging # for adb in accesses.keys(): # flash(adb + ": " + str(accesses[adb]), "info") # # flash("Site admin : " + str(session["site_admin"]), "info") flash('You are successfully logged in.', 'success')
def put(self, dbid, sessid, restype, resid): # we are expected to save the uploaded file and return some info about it: # this is the name for input type=file names = [] # Make sure to read the form before sending the reply jsonresponse = {} jsonresponse["_id"] = request.form['_id'] datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) conn.register([Session]) sessobj = datadb["sessions"].Session.find_one({"_id" : ObjectId(sessid)}) if sessobj == None: return Response("{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405) # Parse headers try: #Get filename from content disposition fnameheader = request.headers["Content-Disposition"] disposition = re.search(r'filename="(.+?)"', fnameheader) filename = disposition.group(0)[10:-1] # Get the actual chunk position from Content-Range range = request.headers["Content-Range"] match = re.findall(r'\d+', range) start = int(match[0]) end = int(match[1]) total = int(match[2]) success = True except: success = False # Headers cannot be parsed, so try if not success: try: bfile = request.files['file'] gf = gridfs.GridFS(datadb , restype) afile = gf.new_file(chunk_size=1048576, filename=bfile.filename, _id=ObjectId(resid)) afile.write(bfile.read()) afile.close() if not sessobj.has_key("attachments"): sessobj["attachments"] = [ {"ref" : ObjectId(resid), "pos" : 0}] if not "images" in sessobj: sessobj["images"] = [] sessobj.validate() sessobj.save() # print "Inserted attachments", str(sessobj["attachments"]) else: size_before = len(sessobj["attachments"]) if not "images" in sessobj: sessobj["images"] = [] sessobj["attachments"].append({"ref" : ObjectId(resid), "pos" : size_before + 1}) sessobj.validate() sessobj.save() return Response("{\"success\" : \" - \"}", status=200) except Exception as e: return Response("{\"error\" : \" Error processing single chunk header" + e.message + " \"}", status=405) # No need to return conventional file list # Expect _id in the form try: jsonresponse["_id"] = request.form['_id'] except: return Response("{\"error\" : \" each put request must include _id requested from server \"}", status=400) n = int(start / 1048576.0) # Craft the response json jsonresponse["start"] = start jsonresponse["end"] = end jsonresponse["total"] = total jsonresponse["done"] = end + 1 bfile = request.files['file'] first = False last = False # If first chunk if start == 0 : first = True jsonresponse["first"] = 1 # Create a file gf = gridfs.GridFS(datadb , restype) afile = gf.new_file(chunk_size=1048576, filename=filename, _id=ObjectId(resid)) afile.write(bfile.read()) afile.close() if total == end + 1: last = True jsonresponse["last"] = 1 # Add the attachment id to the if not sessobj.has_key("attachments"): sessobj["attachments"] = [ {"ref" : ObjectId(resid), "pos" : 0}] sessobj.validate() sessobj.save() # print "Inserted attachments", str(sessobj["attachments"]) else: size_before = len(sessobj["attachments"]) sessobj["attachments"].append({"ref" : ObjectId(resid), "pos" : size_before + 1}) sessobj.validate() sessobj.save() # print "Appended to attachments", str(sessobj["attachments"]) if not first: obj = {} obj["n"] = n obj["files_id"] = ObjectId(resid) obj["data"] = Binary(bfile.read()) datadb["attachments.chunks"].insert(obj) fileobj = datadb["attachments.files"].find_one({"_id" : obj["files_id"]}) datadb["attachments.files"].update({"_id" : obj["files_id"]}, {"$set" : {"length" : fileobj["length"] + len(obj["data"])}}) # Finalize # Append to the chunks collection return jsonify(jsonresponse)
def post(self, resid=None): # post requires admin access # Parse the data in json format data = request.json # Unknown request if no parameters if data == None: abort(400) conn.register([Database]) # Only insert command is supported if data.has_key("insert"): # Create the database object from the supplied parameters try: if resid <> None: raise Exception( "Trying to create new resource at existing resource") newdb = conn[ current_app.config["CONFIGDB"]]["databases"].Database() newdb["label"] = data["insert"]["label"] newdb["host"] = data["insert"]["host"] newdb["dbname"] = data["insert"]["dbname"] newdb["copyright"] = data["insert"]["copyright"] newdb.validate() newdb.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) return jsonify(newdb) elif data.has_key("modify"): # Resid must be supplied if resid == None: return Response( "{\"error\" : \"No resource id supplied for modification\"}", status=405) try: # Locate the resource newdb = conn[current_app.config["CONFIGDB"]][ "databases"].Database.find_one({"_id": ObjectId(resid)}) if newdb == None: raise Exception(" Resource %s not found" % (resid)) except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) # Now update try: for akey in data["modify"]: if akey == "_id": return Response("{\"error\" : \"Cannot modify _id \"}", status=405) # Update other keys if akey in newdb: newdb[akey] = data["modify"][akey] newdb.validate() newdb.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : \"%s\"}" % str(inst), status=405) return jsonify(newdb) else: # Only insert and modify commands supported so far abort(400)
def sessions(): """ - /sessions With no argument displays list of sessions accessible to current user - /sessions?sessid=10239094124 searches for the session id """ rules = [] # Compile the rules conn.register([Image, Session, User, Rule, Database]) admindb = conn[current_app.config["CONFIGDB"]] #pdb.set_trace() # Assert the user is logged in if 'user' in session: name = session['user']['label'] id = session['user']['id'] userobj = admindb["users"].User.find_one({"_id": ObjectId(id)}) if userobj == None: # If the user is not found then something wrong # Redirect the user to home with error message flash("Invalid login", "error") return redirect(url_for('login.login')) else: # Send the user back to login page # with some message flash("You must be logged in to see that resource", "error") return redirect(url_for('login.login')) # This code gets executed only if the user information is available # See if the user is requesting any session id sessid = request.args.get('sessid', None) sessdb = request.args.get('sessdb', "") ajax = request.args.get('json', None) next = int(request.args.get('next', 0)) if sessid: # Find and return image list from single session # TODO: Refactor this into a function db = admindb access = True # eventually sessdb will go away. if sessdb != "": access = False dbobj = admindb["databases"].Database.find_one( {"_id": ObjectId(sessdb)}) db = conn[dbobj["dbname"]] # From rules pertaining to current user try: for arule in userobj["rules"]: ruleobj = admindb["rules"].Rule.find_one({"_id": arule}) if str(ruleobj["db"]) == sessdb: if 'db_admin' in ruleobj and ruleobj[ "db_admin"] == True: access = True elif 'can_see_all' in ruleobj and ruleobj[ "can_see_all"] == True: access = True elif len(ruleobj["can_see"]) > 0: for asession in ruleobj["can_see"]: if str(asession) == sessid: access = True except: pass # Confirm that the user has access if access == False: flash("Unauthorized access", "error") return redirect("/home") coll = db["sessions"] asession = coll.find_one({'_id': ObjectId(sessid)}, { 'images': { '$slice': [next, NUMBER_ON_PAGE] }, '_id': 0 }) # Hide notes and descriptive title for student review hideAnnotations = False if "hideAnnotations" in asession: if asession["hideAnnotations"]: hideAnnotations = True else: asession["hideAnnotations"] = False # iterate through the session objects images = [] if asession.has_key("views"): for aview in asession['views']: hide = False if 'hide' in aview: if aview["hide"]: hide = True viewobj = db["views"].find_one({"_id": aview["ref"]}) # Crash here. Session had a viewid that did not exist. # Should we clean up the broken reference? Just skip for now. if viewobj: imgid = 0 imgdb = "" imgobj = None if "Type" in viewobj: # my new notes make it difficult to get the image. if viewobj["Type"] == "Note": if viewobj["ViewerRecords"][0].has_key("Database"): imgid = viewobj["ViewerRecords"][0]["Image"] imgdb = viewobj["ViewerRecords"][0]["Database"] else: imgid = viewobj["ViewerRecords"][0]["Image"][ "_id"] imgdb = viewobj["ViewerRecords"][0]["Image"][ "database"] if imgid == 0: imgdb = sessdb imgid = str(viewobj["img"]) if "imgdb" in viewobj: imgdb = viewobj["imgdb"] if imgdb == sessdb: imgobj = db["images"].find_one( {'_id': ObjectId(imgid)}, {'_id': 0}) else: dbobj2 = admindb["databases"].Database.find_one( {"_id": ObjectId(imgdb)}) #TODO: make sure the connection to host is available db2 = conn[dbobj2["dbname"]] imgobj = db2["images"].find_one( {'_id': ObjectId(imgid)}, {'_id': 0}) # so many legacy schemas (plus hiding annotation) label = "" if "label" in imgobj: label = imgobj["label"] if "label" in aview: label = aview["label"] if "Title" in viewobj: label = viewobj["Title"] if hideAnnotations: label = viewobj["HiddenTitle"] if 'hide' in imgobj: if imgobj["hide"]: hide = True if 'hide' in viewobj: if viewobj["hide"]: hide = True if not hide: if imgobj.has_key("thumb"): del imgobj['thumb'] animage = {} animage['db'] = imgdb animage["img"] = imgid animage["label"] = label animage["view"] = str(aview["ref"]) if "type" in viewobj: if viewobj["type"] == "comparison": animage["comparison"] = 1 images.append(animage) attachments = [] if asession.has_key("attachments"): gfs = GridFS(db, "attachments") for anattach in asession['attachments']: fileobj = gfs.get(anattach["ref"]) attachments.append({ 'name': fileobj.name, 'id': anattach["ref"] }) del asession["attachments"] if 'images' in asession: del asession["images"] data = { 'success': 1, 'session': asession, 'images': images, 'attachments': attachments, 'db': sessdb, 'sessid': sessid, 'next': url_for('session.sessions', sessid=sessid, ajax=1, next=next + NUMBER_ON_PAGE) } if ajax: return jsonify(data) else: return render_template('session.html', data=data, name=name) else: # Compile a list of session names / ids sessionlist = [] # sessions owned by this user. rule = {} rule["rule"] = "" sessions = [] for sessionobj in admindb["sessions"].find(): thissession = { 'sessid': str(sessionobj["_id"]), 'label': sessionobj["label"], 'sessdb': "" } sessions.append(thissession) rule["sessions"] = sessions sessionlist.append(rule) # From rules pertaining to current user if "rules" in userobj: for arule in userobj["rules"]: rule = {} ruleobj = admindb["rules"].Rule.find_one({"_id": arule}) if ruleobj == None: continue #flash(str(ruleobj), 'success') rule["rule"] = ruleobj["label"] # Find the db pertaining to this rule dbobj = admindb["databases"].Database.find_one( {"_id": ruleobj["db"]}) # TODO: initiate new connection if required with this database db = conn[dbobj["dbname"]] sessions = [] if 'can_see_all' in ruleobj and ruleobj["can_see_all"] == True: #flash("All" + ruleobj["label"], "success") # Gets access to see / admin all sessions in this DB for sessionobj in db["sessions"].Session.find(): thissession = { 'sessid': str(sessionobj["_id"]), 'label': sessionobj["label"], 'sessdb': str(dbobj["_id"]) } if 'type' in sessionobj: if (sessionobj["type"] == "stack"): thissession["stack"] = True sessions.append(thissession) elif len(ruleobj["can_see"]) > 0: # Gets access to a limited number of sessions for asession in ruleobj["can_see"]: sessionobj = db["sessions"].Session.find_one( {"_id": asession}) if sessionobj == None: continue thissession = { 'sessid': str(sessionobj["_id"]), 'label': sessionobj["label"], 'sessdb': str(dbobj["_id"]) } if 'type' in sessionobj: if (sessionobj["type"] == "stack"): thissession["stack"] = True sessions.append(thissession) # if db administrator if 'db_admin' in ruleobj and ruleobj["db_admin"] == True: # Update the administrative for asession in sessions: #flash("Admin session: " + asession["label"] , "success") asession["canadmin"] = True rule["sessions"] = sessions sessionlist.append(rule) # End of for loop over rules if ajax: return jsonify(sessions=sessionlist, name=name, ajax=1) else: return render_template('sessionlist.html', sessions=sessionlist, name=name)
def put(self, dbid, sessid, restype, resid): # we are expected to save the uploaded file and return some info about it: # this is the name for input type=file names = [] # Make sure to read the form before sending the reply jsonresponse = {} jsonresponse["_id"] = request.form['_id'] datadb = self.get_data_db(dbid) if datadb == None: return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) conn.register([Session]) sessobj = datadb["sessions"].Session.find_one( {"_id": ObjectId(sessid)}) if sessobj == None: return Response( "{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405) # Parse headers try: #Get filename from content disposition fnameheader = request.headers["Content-Disposition"] disposition = re.search(r'filename="(.+?)"', fnameheader) filename = disposition.group(0)[10:-1] # Get the actual chunk position from Content-Range range = request.headers["Content-Range"] match = re.findall(r'\d+', range) start = int(match[0]) end = int(match[1]) total = int(match[2]) success = True except: success = False # Headers cannot be parsed, so try if not success: try: bfile = request.files['file'] gf = gridfs.GridFS(datadb, restype) afile = gf.new_file(chunk_size=1048576, filename=bfile.filename, _id=ObjectId(resid)) afile.write(bfile.read()) afile.close() if not sessobj.has_key("attachments"): sessobj["attachments"] = [{ "ref": ObjectId(resid), "pos": 0 }] sessobj.validate() sessobj.save() # print "Inserted attachments", str(sessobj["attachments"]) else: size_before = len(sessobj["attachments"]) sessobj["attachments"].append({ "ref": ObjectId(resid), "pos": size_before + 1 }) sessobj.validate() sessobj.save() return Response("{\"success\" : \" - \"}", status=200) except: return Response( "{\"error\" : \" Error processing single chunk header \"}", status=405) # No need to return conventional file list # Expect _id in the form try: jsonresponse["_id"] = request.form['_id'] except: return Response( "{\"error\" : \" each put request must include _id requested from server \"}", status=400) n = int(start / 1048576.0) # Craft the response json jsonresponse["start"] = start jsonresponse["end"] = end jsonresponse["total"] = total jsonresponse["done"] = end + 1 bfile = request.files['file'] first = False last = False # If first chunk if start == 0: first = True jsonresponse["first"] = 1 # Create a file gf = gridfs.GridFS(datadb, restype) afile = gf.new_file(chunk_size=1048576, filename=filename, _id=ObjectId(resid)) afile.write(bfile.read()) afile.close() if total == end + 1: last = True jsonresponse["last"] = 1 # Add the attachment id to the if not sessobj.has_key("attachments"): sessobj["attachments"] = [{"ref": ObjectId(resid), "pos": 0}] sessobj.validate() sessobj.save() # print "Inserted attachments", str(sessobj["attachments"]) else: size_before = len(sessobj["attachments"]) sessobj["attachments"].append({ "ref": ObjectId(resid), "pos": size_before + 1 }) sessobj.validate() sessobj.save() # print "Appended to attachments", str(sessobj["attachments"]) if not first: obj = {} obj["n"] = n obj["files_id"] = ObjectId(resid) obj["data"] = Binary(bfile.read()) datadb["attachments.chunks"].insert(obj) fileobj = datadb["attachments.files"].find_one( {"_id": obj["files_id"]}) datadb["attachments.files"].update( {"_id": obj["files_id"]}, {"$set": { "length": fileobj["length"] + len(obj["data"]) }}) # Finalize # Append to the chunks collection return jsonify(jsonresponse)
def put(self, resid): # put requires admin access # Get json supplied data = request.json # Check for valid parameters # Check if no parameters if data == None: return Response("{\"error\" : \"No parameters ? \"}", status=405) # See if id matches the resource being modified try: if data["_id"] != resid: raise Exception(1) except: # # def delete(self, dbid, sessid, restype, resid=None): # if resid == None: # return Response("{ \"error \" : \"Deletion of all attachments not implemented Must provide resid\"}" , status=405) # else: # datadb = self.get_data_db(dbid) # if datadb == None: # return Response("{ \"error \" : \"Invalid database id %s\"}" % (dbid), status=405) # # # TODO: This block of code to common and can be abstrated # conn.register([Session]) # sessobj = datadb["sessions"].Session.find_one({"_id" : ObjectId(sessid)}) # if sessobj == None: # return Response("{ \"error \" : \"Session %s does not exist in db %s\"}" % (sessid, dbid), status=405) # # if restype == "attachments" or restype == "rawfiles": # # Remove from the gridfs # gf = gridfs.GridFS(datadb , restype) # gf.delete(ObjectId(resid)) # # # Remove the reference from session # attachments = [value for value in sessobj["attachments"] if value["ref"] != ObjectId(resid)] # # Find the index # # Remove that index # sessobj["attachments"] = attachments # # if not "images" in sessobj: # sessobj["images"] = [] # sessobj.validate() # sessobj.save() # return Response("{ \"Success \" : \" \"}", status=200) # else: # return "You want %s from views in %s/%s" % (resid, dbid, sessid) return Response("{\"error\" : \"_id mismatch with the location in the url \"}", status=405) # Try to see if the data can create valid object conn.register([Database]) # The object should exist dbobj = conn[current_app.config["CONFIGDB"]]["databases"].Database.find_one({"_id" : ObjectId(resid)}) # Unknown request if no parameters if dbobj == None: return Response("{\"error\" : \"Resource _id: %s doesnot exist\"}" % (resid), status=403) # Create the database object from the supplied parameters try: dbobj["label"] = data["label"] dbobj["host"] = data["host"] dbobj["dbname"] = data["dbname"] dbobj["copyright"] = data["copyright"] dbobj.validate() dbobj.save() except Exception as inst: # If valid database object cannot be constructed it is invalid request return Response("{\"error\" : %s}" % str(inst), status=405) return jsonify(dbobj)