def captcha(publicID): publicID = publicID.lower() session_info = session_db.find_one({"publicID": publicID}, {"_id": 0}) hancock = Signer(str(secret_key), salt=str(session_info["privateID"])) if (publicID + "-guest") in request.cookies and hancock.validate( request.cookies.get(publicID + "-guest")): return redirect("https://www.crowdsourcejukebox.com/vote/" + publicID + "/") if request.method == "POST": captcha_response = request.form["g-recaptcha-response"] if is_human(captcha_response): resp = make_response( redirect("https://www.crowdsourcejukebox.com/vote/" + publicID + "/")) guestID = bytes(str(uuid.uuid4()), "utf-8") session_db.update_one({"publicID": publicID}, {"$inc": { "guests": 1 }}) resp.set_cookie( publicID + "-guest", value=hancock.sign(guestID), expires=datetime.datetime.now() + datetime.timedelta(hours=1), ) return resp else: return redirect("http://www.crowdsourcejukebox.com/") else: return render_template("captcha.html", sitekey=os.environ["RC_SITE_KEY"])
def user_loader(session_token): signer = Signer(current_app.config["SECRET_KEY"]) # verify the token we're getting hasn't been tampered with. if not signer.validate(session_token): current_app.logger.critical(f"bad signature from user's session token: {session_token}") return u = Users.query.filter(Users.session_token == str(session_token)).first() if u: # verify token to make sure it hasn't been tampered with while in the database if not signer.validate(u.session_token): current_app.logger.critical( f"bad signature from stored session token: {u.session_token}") return current_app.logger.debug( f"loaded user by session token. user: {u} token: {u.session_token}") return u
def search(publicID): publicID = publicID.lower() now = int(time.time()) session_info = session_db.find_one({"publicID": publicID}, {"_id": 0}) if session_info is None: return redirect("http://www.crowdsourcejukebox.com/"), 301 session_db.update_one({"publicID": publicID}, {"$set": { "lastaccessed": now, "lastread": now }}) hancock = Signer(secret_key, salt=session_info["privateID"]) if (publicID + "-guest") not in request.cookies: return redirect("http://www.csjb.cc/" + publicID) else: if not hancock.validate(request.cookies.get(publicID + "-guest")): abort(401) if (session_info["settings"]["songlimit"] and setlist_db[publicID].find_one( { "played": 0, "submitted_by": request.cookies.get(publicID + "-guest") }) is not None): print("got one", file=sys.stderr) return render_template("search.html", publicID=publicID, wait=True) query = request.query_string.decode("UTF-8") if query != "" and "query=" in query: query = query[query.index("query="):] query = query[query.index("=") + 1:] query = query if "&" not in query else query[:query.index("&")] if query == "": return render_template("search.html", publicID=publicID, wait=False) query = urllib.parse.unquote_plus(query) results = sp.search(query, limit=35)["tracks"]["items"] if session_info["settings"]["noexplicit"]: results = [x for x in results if not x["explicit"]] tracks = [{ "uri": result["uri"], "image": result["album"]["images"][0]["url"], "name": result["name"], "artist": result["artists"][0]["name"], } for result in results] return render_template("results.html", tracks=tracks, publicID=publicID, prev_query=query) else: return render_template("search.html", publicID=publicID, wait=False)
def api(): now = int(time.time()) form = {key: request.form[key] for key in request.form.keys()} authorized_requests = [ "newID", "unload", "setlist", "updates", "public", "playnext", "vote", "submit", "settings", "setFallback", ] if "req" not in form.keys() or form["req"] not in authorized_requests: abort(400) print("request:", form, file=sys.stderr) return_obj = {} if form["req"] == "newID": setlists = setlist_db.list_collection_names() to_drop = session_db.find( {"lastaccessed": { "$lt": now - (60 * INACTIVE_TIMEOUT) }}) to_drop = [s["publicID"] for s in to_drop] if to_drop != []: print(to_drop, flush=True) for s in to_drop: if s in setlists: setlist_db[s].drop() session_db.delete_many( {"lastaccessed": { "$lt": now - (60 * INACTIVE_TIMEOUT) }}) return_obj = newID() killSession(form["oldID"], hard=True) if form["req"] == "unload": killSession(form["oldID"], hard=True) if form["req"] == "playnext": publicID = session_db.find_one({"privateID": form["privateID"]})["publicID"] return_obj = list(setlist_db[publicID].find({ "played": 0, "upvotes": { "$gte": 0 } })) if return_obj == []: past_played = [ x for x in setlist_db[publicID].find({"played": 1}, {"_id": 0}) ] top_played = sorted(past_played, reverse=True, key=lambda i: i["upvotes"]) if len(top_played) > 20: top_played = top_played[:int(len(top_played) / 2)] seeds = [] for i in range(4): seeds.append( top_played.pop(random.randint(0, len(top_played) - 1))["uri"]) nextsong = sp.recommendations(seed_tracks=seeds, limit=1)["tracks"][0] return_obj = {"uri": nextsong["uri"], "upvotes": 0} else: return_obj = sorted(return_obj, reverse=True, key=lambda i: i["upvotes"])[0] setlist_db[publicID].update_one({"_id": return_obj.pop("_id")}, {"$set": { "played": 1 }}) session_db.update_one( {"privateID": form["privateID"]}, {"$set": { "lastaccessed": now, "lastmodified": now }}, ) if form["req"] == "setlist": form["number"] = int(form["number"]) return_obj = list(setlist_db[form["publicID"]].find({"played": 0}, {"_id": 0})) return_obj = sorted(return_obj, reverse=True, key=lambda i: i["upvotes"]) return_obj = (return_obj if form["number"] > len(return_obj) else return_obj[:form["number"]]) session_db.update_one( {"publicID": form["publicID"]}, {"$set": { "lastaccessed": now, "lastread": now }}, ) if form["req"] == "updates": now = int(time.time()) session = session_db.find_one({"publicID": form["publicID"]}) return_obj = {"update": session["lastmodified"] > now - 7} session_db.update_one( {"publicID": form["publicID"]}, {"$set": { "lastaccessed": now, "lastread": now }}, ) if form["req"] == "public": session_db.update_one( {"privateID": form["privateID"]}, {"$set": { "lastaccessed": now, "lastread": now }}, ) info = session_db.find_one({"privateID": form["privateID"]}) return_obj = {"publicID": info["publicID"], "display": info["display"]} if form["req"] == "vote": guestID = form["guestID"] session_info = session_db.find_one({"publicID": form["publicID"]}, {"_id": 0}) hancock = Signer(secret_key, salt=session_info["privateID"]) if not hancock.validate(guestID): abort(401) publicID = form["publicID"] uri = form["uri"] direction = form["direction"] entry = setlist_db[publicID].find_one({"played": 0, "uri": uri}) entry["upvoters"] = [] if "upvoters" not in entry.keys( ) else entry["upvoters"] entry["downvoters"] = ([] if "downvoters" not in entry.keys() else entry["downvoters"]) # print(guestID) if direction == "up": if guestID in entry["downvoters"]: entry["downvoters"].remove(guestID) # if guestID in entry["upvoters"]: # entry["upvoters"].remove(guestID) if guestID not in entry["upvoters"]: entry["upvoters"].append(guestID) if direction == "down": if guestID in entry["upvoters"]: entry["upvoters"].remove(guestID) # if guestID in entry["downvoters"]: # entry["downvoters"].remove(guestID) if guestID not in entry["downvoters"]: entry["downvoters"].append(guestID) if direction == "neutral": if guestID in entry["upvoters"]: entry["upvoters"].remove(guestID) if guestID in entry["downvoters"]: entry["downvoters"].remove(guestID) entry["upvotes"] = len(entry["upvoters"]) - len(entry["downvoters"]) # print(entry["upvoters"]) # print(entry["downvoters"]) if len(entry["downvoters"]) > int(0.6 * session_info["guests"]) or ( direction == "down" and guestID == entry["submitted_by"]): setlist_db[publicID].delete_one({"_id": entry["_id"]}) else: setlist_db[publicID].update_one({"_id": entry["_id"]}, {"$set": entry}) session_db.update_one( {"publicID": form["publicID"]}, {"$set": { "lastaccessed": now, "lastmodified": now }}, ) if form["req"] == "submit": guestID = form["guestID"] session_info = session_db.find_one({"publicID": form["publicID"]}, {"_id": 0}) hancock = Signer(secret_key, salt=session_info["privateID"]) if not hancock.validate(guestID): abort(401) publicID = form["publicID"] uri = form["uri"] if (session_info["settings"]["songlimit"] and setlist_db[publicID].find_one({ "played": 0, "submitted_by": guestID }) is not None): abort(403) entry = setlist_db[publicID].find_one({"played": 0, "uri": uri}) if entry is not None: # if the song is already in the setlist: entry["upvoters"] = ([] if "upvoters" not in entry.keys() else entry["upvoters"]) entry["downvoters"] = ([] if "downvoters" not in entry.keys() else entry["downvoters"]) if guestID in entry["downvoters"]: entry["downvoters"].remove(guestID) if guestID not in entry["upvoters"]: entry["upvoters"].append(guestID) entry["upvotes"] = len(entry["upvoters"]) - len( entry["downvoters"]) setlist_db[publicID].update_one({"_id": entry["_id"]}, {"$set": entry}) else: return_obj = { "uri": uri, "upvoters": [guestID], "downvoters": [], "submitted_by": guestID, "played": 0, "upvotes": 1, } setlist_db[publicID].insert_one(return_obj) return_obj.pop("_id") session_db.update_one( {"publicID": form["publicID"]}, {"$set": { "lastaccessed": now, "lastmodified": now }}, ) # session_db.update_one({"publicID": publicID}, {"$set":{"lastaccessed": now, "lastmodified":now}}) if form["req"] == "settings": # print(str(form), file=sys.stderr) session_info = session_db.find_one({"privateID": form["privateID"]}, {"_id": 0}) if session_info is None: abort(404) settings = { "noexplicit": form["noexplicit"] == "true", "songlimit": form["songlimit"] == "true", "voteoff": form["voteoff"] == "true", "captcha": form["captcha"] == "true", } # print(settings, file=sys.stderr) session_db.update_one( {"privateID": form["privateID"]}, { "$set": { "lastaccessed": now, "lastmodified": now, "settings": settings } }, ) return_obj = session_db.find_one({"privateID": form["privateID"]}, {"_id": 0}) if settings["noexplicit"]: tmp_playlist = list(setlist_db[session_info["publicID"]].find( { "played": 0 }, { "_id": 0 }).sort("upvotes", -1)) tracks = [] while len(tmp_playlist) >= 50: tracks += sp.tracks([x["uri"] for x in tmp_playlist[:50]])["tracks"] tmp_playlist = tmp_playlist[50:] tracks += sp.tracks([x["uri"] for x in tmp_playlist])["tracks"] tracks = [t["uri"] for t in tracks if t["explicit"]] setlist_db[session_info["publicID"]].delete_many( {"uri": { "$in": tracks }}) if form["req"] == "setFallback": session_info = session_db.find_one({"privateID": form["privateID"]}, {"_id": 0}) if session_info is None: abort(404) setlist_db[session_info["publicID"]].delete_many( {"submitted_by": "fallback"}) to_insert = sp.user_playlist(form["user"], form["uri"])["tracks"]["items"] if session_info["settings"]["noexplicit"]: for track in to_insert: # print(track["track"], file=sys.stderr) if track["track"]["explicit"]: to_insert.remove(track) to_insert = [{ "uri": x["track"]["uri"], "upvotes": 0, "submitted_by": "fallback", "upvoters": [], "downvoters": [], "played": 0, } for x in to_insert] # return_obj = to_insert setlist_db[session_info["publicID"]].insert_many(to_insert) session_db.update_one( {"privateID": form["privateID"]}, {"$set": { "lastaccessed": now, "lastmodified": now }}, ) # return_obj.pop("_id") print("response:", return_obj, file=sys.stderr) return jsonify(return_obj)
def vote(publicID): publicID = publicID.lower() now = int(time.time()) session_info = session_db.find_one({"publicID": publicID}, {"_id": 0}) if session_info is None: abort(404) session_db.update_one({"publicID": publicID}, {"$set": { "lastaccessed": now, "lastread": now }}) current_playlist = list(setlist_db[publicID].find({ "played": 0 }, { "_id": 0 }).sort("upvotes", -1)) if current_playlist != []: tmp_playlist = current_playlist tracks = [] while len(tmp_playlist) >= 49: tracks += sp.tracks([x["uri"] for x in tmp_playlist[:45]])["tracks"] tmp_playlist = tmp_playlist[45:] tracks += sp.tracks([x["uri"] for x in tmp_playlist])["tracks"] for t in range(len(tracks)): curr_track = current_playlist[t] if publicID + "-guest" in request.cookies: if ("upvoters" in curr_track.keys() and request.cookies[publicID + "-guest"] in curr_track["upvoters"]): curr_track["vote"] = "up" # curr_track["upvotes"] -= 1 elif ("downvoters" in curr_track.keys() and request.cookies[publicID + "-guest"] in curr_track["downvoters"]): curr_track["vote"] = "down" # curr_track["upvotes"] += 1 else: curr_track["vote"] = "neutral" else: curr_track["vote"] = "neutral" curr_track["image"] = tracks[t]["album"]["images"][1]["url"] curr_track["name"] = tracks[t]["name"] # curr_track["album"] = tracks[t]["album"]["name"] curr_track["artist"] = tracks[t]["artists"][0]["name"] resp = make_response( render_template("vote.html", publicID=publicID, tracks=current_playlist)) hancock = Signer(str(secret_key), salt=str(session_info["privateID"])) if (publicID + "-guest") not in request.cookies: # print(session_info["settings"], file=sys.stderr) if session_info["settings"]["captcha"]: return redirect("https://www.crowdsourcejukebox.com/captcha/" + publicID + "/") else: guestID = bytes(str(uuid.uuid4()), "utf-8") session_db.update_one({"publicID": publicID}, {"$inc": { "guests": 1 }}) resp.set_cookie( publicID + "-guest", value=hancock.sign(guestID), expires=datetime.datetime.now() + datetime.timedelta(hours=1), ) else: if not hancock.validate(request.cookies.get(publicID + "-guest")): abort(401) # guestID = hancock.unsign(request.cookies.get(publicID + "-guest")) return resp
class User(): def __init__(self,secret_key): #initialize signer self.s = Signer(secret_key) def deserialize(self,request): #it runs in framework BEFORE_REQUEST function self.cookies = request.cookies #check stat in cookie and verify it stat_str = str(self.cookies.get('stat')) stat_signature = str(self.cookies.get('stat_signature')) stat_token = stat_str+'.'+stat_signature if stat_str=='None' or self.s.validate(stat_token)==False: self._create_new_stat(request) #if validation success else: self.stat = json.loads(stat_str) #increase kolvo_visits self._increase_kolvo_visits() #add actual IP for checking log_token self.stat['ip'] = request.environ['REMOTE_ADDR'] self.log_token = str(self.cookies.get('log_token')) #initialize DB self._db_init() def serialize(self,response): #it runs in framework AFTER_REQUEST function stat_str = json.dumps(self.stat) sign_str = self.s.sign(stat_str) last_elem = len(sign_str.split('.')) #because dots in IP self.stat_signature = sign_str.split('.')[last_elem-1] response.set_cookie('stat',value=stat_str) response.set_cookie('stat_signature',value=self.stat_signature) if self.log_token!='None': response.set_cookie('log_token',value=self.log_token) else: response.set_cookie('log_token','',expires=0) #increase visits return response def _create_new_stat(self,request): self.stat = {} self.stat['ip'] = request.environ['REMOTE_ADDR'] self.stat['first_reg'] = int(time.time()) self.stat['kolvo_visits'] = 1 self.stat['_id'] = 'yap'+str(int(time.time())) self.stat['last_visit'] = int(time.time()/86400) def _increase_kolvo_visits(self): new_day = int(time.time()/86400) if self.stat.get('last_visit')==None: self.stat['last_visit'] = int(time.time()/86400) if int(self.stat.get('last_visit'))<new_day: self.stat['kolvo_visits'] = self.stat['kolvo_visits']+1 self.stat['last_visit'] = new_day def check_auth(self,roles): if self.log_token=='None': return 'Error User:Not Login, Please Log IN' if self.s.validate(self.log_token)!=True: return 'Error User:Not Valid Login Token. Please, Log IN' self.session = self._get_json(self.log_token) if self.session['ip']!=self.stat['ip']: return 'Error User:Not valid IP. Please, log IN' if (int(time.time()) - int(self.session['ts']))>int(self.session['live_time']): return 'Error User:Session nor fresh, please Log IN' #check permission for each in self.session['roles']: if each in roles: return True return 'Error User:Not enough permission' def _gen_token(self,user_id,u_doc): self.session = {} self.session['_id'] = user_id self.session['name'] = u_doc['name'] self.session['ts'] = int(time.time()) self.session['roles'] = u_doc['roles'] self.session['live_time'] = u_doc.get('token_live_time') self.session['ip'] = self.stat['ip'] #create JSON from dict and compress j = json.dumps(self.session) j64 = base64.b64encode(j) #create signature j64_sign = self.s.sign(j64) return j64_sign def _get_json(self,token): if self.s.validate(token)!=True: return 'Error User: not valid Log Token' jb64 = self.s.unsign(token) j = base64.b64decode(jb64) j = json.loads(j) return j def login(self,user_name,user_pass): #if user id in db and pass is equal md5 with secret #check user name and get user doc u_doc,u_id = self._db_check_in(user_name) if u_doc==False: return 'Error User:No such User' #check pass if self._md5_trans(user_pass)!=u_doc['pass']: return 'Error User:Wrong Pass' self.log_token = self._gen_token(u_id, u_doc) return True def registr(self,u_doc): user_id = 'yap'+str(int(time.time())) if self._db_check_in(u_doc['name'])!=[False,False]: return 'Error User:There is user with the name '+u_doc['name'] u_doc['pass'] = self._md5_trans(u_doc['pass']) self._db_add(user_id,u_doc) return True def drop_log_token(self): self.log_token = 'None' return True def _md5_trans(self,rec): m = md5.new() m.update(rec) return m.hexdigest() ########## DB ################# def _db_init(self): cl = MongoClient('localhost',27017) _db = cl['users'] self.db = _db['users'] def _db_check_in(self,u_name): u_doc = self.db.find_one({'name':u_name}) if u_doc==None: return [False,False] return u_doc,u_doc['_id'] def _db_add(self,u_id,user_d): user_d['_id'] = u_id self.db.insert_one(user_d)