def api_comment_allow_user(comment_id): comment = db.session.query(TComments).filter(TComments.comments_id == comment_id).first() if comment: addr = db.session.query(TEmail).filter(TEmail.email == comment.email).first() if addr: setattr(addr, 'is_allowed', True) setattr(addr, 'is_blocked', False) else: new_mail = { "email": comment.email, "is_allowed": True, "is_blocked": False } db.session.add(TEmail(**new_mail)) # Allow all comments made by this mail address all_comments = db.session.query(TComments).filter(TComments.email == comment.email).all() if all_comments: for comment in all_comments: setattr(comment, 'is_published', True) setattr(comment, 'is_spam', False) db.session.commit() # Get location id from get params location_id = request.args.get('location') export_location(location_id) return redirect(request.referrer)
def api_comments_delete_comment(comment_id): db.session.query(TComments).filter(TComments.comments_id == comment_id).delete() db.session.commit() # Get location id from get params location_id = request.args.get('location') export_location(location_id) return redirect(request.referrer)
def api_comment_allow_comment(comment_id): comment = db.session.query(TComments).filter(TComments.comments_id == comment_id).first() if comment: setattr(comment, 'is_published', True) setattr(comment, 'is_spam', False) db.session.commit() # Get location id from get params location_id = request.args.get('location') export_location(location_id) return redirect(request.referrer)
def api_export_all_by_project(name): proj_id = get_id_from_project_name(name) if proj_id == -1: return make_response(jsonify(status='not-found'), 400) try: locations = db.session.query(TLocation).all() for each in locations: export_location(each.id_location) except Exception as e: return make_response(jsonify(status='sql-error', msg=str(e)), 400) return make_response(jsonify(status='ok'), 200)
def check_deletion_link(name, email_hash): project = db.session.query(TProjects).filter( TProjects.name == name).first() comment = db.session.query(TComments).filter( TComments.deletion == email_hash).first() if comment: location = db.session.query(TLocation).filter( TLocation.id_location == comment.location_id).first() if compare_digest(comment.deletion, email_hash): db.session.delete(comment) db.session.commit() url = f"{project.blogurl}?deleted=true" export_location(location.id_location) return redirect(url) return redirect(f"{project.blogurl}?cnf=true")
def check_confirmation_link(name, email_hash): comment = db.session.query(TComments).filter( TComments.confirmation == email_hash).first() project = db.session.query(TProjects).filter( TProjects.name == name).first() if comment: location = db.session.query(TLocation).filter( TLocation.id_location == comment.location_id).first() if compare_digest(comment.confirmation, email_hash): comment.confirmation = None if not comment.is_spam: setattr(comment, "is_published", True) db.session.commit() url = f"{project.blogurl}{location.location}#comment_{comment.comments_id}" export_location(location.id_location) return redirect(url) return redirect(f"{project.blogurl}?cnf=true")
def api_comment_block_mail(comment_id): comment = db.session.query(TComments).filter(TComments.comments_id == comment_id).first() if comment: addr = db.session.query(TEmail).filter(TEmail.email == comment.email).first() if addr: setattr(addr, 'is_allowed', False) setattr(addr, 'is_blocked', True) else: new_mail = { "email": comment.first().email, "is_allowed": False, "is_blocked": True } db.session.add(TEmail(**new_mail)) # Delete all comments made by this mail address db.session.query(TComments).filter(TComments.email == comment.email).delete() db.session.commit() # Get location id from get params location_id = request.args.get('location') export_location(location_id) return redirect(request.referrer)
def check_and_insert_new_comment(name): # Get project project = db.session.query(TProjects).filter( TProjects.name == name).first() # Check refferer, this is not bullet proof if not compare_digest(request.origin, project.blogurl): return make_response(jsonify(status="not-allowed"), 403) if not project: return make_response(jsonify(status="post-project-not-found"), 400) if compare_digest(request.method, "POST"): smileys = Smileys() sender = Mail() # Check length of content and abort if too long or too short if request.content_length > 2048: return make_response(jsonify(status="post-max-length"), 400) if request.content_length == 0: return make_response(jsonify(status="post-min-length"), 400) # get json from request new_comment = request.json # save and sanitize location, nice try, bitch location = new_comment['location'].strip().replace('.', '') # Validate json and check length again if not is_valid_json(new_comment) or \ len(new_comment['content']) < 40 or \ len(new_comment['email']) < 5: return make_response(jsonify(status='post-invalid-json'), 400) # Strip any HTML from message body tags = re.compile('<.*?>') special = re.compile('[&].*[;]') content = re.sub(tags, '', new_comment['content']).strip() content = re.sub(special, '', content).strip() # Convert smileys if enabled if project.addon_smileys: for key, value in smileys.smileys.items(): content = content.replace(key, value) # Validate replied_to field is integer replied_to = new_comment['replied_to'] try: if replied_to: replied_to = int(replied_to) # not a valid id at all except ValueError: return make_response(jsonify(status="bad-reply"), 400) # Update values new_comment.update({"content": content}) new_comment.update({"email": new_comment['email'].strip()}) new_comment.update({"location": location}) new_comment.update({"replied_to": replied_to}) # Check mail if not sender.validate(new_comment['email']): return make_response(jsonify(status='post-invalid-email'), 400) # check for spam is_spam = spam(new_comment['content']) has_score = score(new_comment['content']) # Insert mail into spam if detected, allow if listed as such email = db.session.query(TEmail).filter( TEmail.email == new_comment['email']).first() if not email: if is_spam: entry = { "email": new_comment['email'], "is_blocked": True, "is_allowed": False } db.session.add(TEmail(**entry)) if email: if not email.is_allowed: is_spam = True if email.is_allowed: # This forces the comment to be not spam if the address is in the allowed list, # but the commenter will still need to confirm it to avoid brute # force attacks against this feature is_spam = False # Look for location loc_query = db.session.query(TLocation) \ .filter(TLocation.location == new_comment['location']) if loc_query.first(): # Location exists, set existing location id new_comment.update({'location_id': loc_query.first().id_location}) # TComments does not have this field new_comment.pop("location") else: # Insert new location loc_table = { 'location': new_comment['location'], 'project_id': project.id_project } new_loc = TLocation(**loc_table) db.session.add(new_loc) db.session.flush() db.session.refresh(new_loc) new_comment.update({'location_id': new_loc.id_location}) # TComments does not have this field new_comment.pop("location") # insert comment # noinspection PyBroadException try: if project.sendotp: new_comment.update({"is_published": False}) else: new_comment.update({"is_published": True}) new_comment.update({"created_on": default_timestamp()}) new_comment.update({"is_spam": is_spam}) new_comment.update({"spam_score": has_score}) new_comment.update({ "gravatar": check_gravatar(new_comment['email'], project.name) }) new_comment.update({"project_id": project.id_project}) t_comment = TComments(**new_comment) db.session.add(t_comment) db.session.commit() db.session.flush() db.session.refresh(t_comment) # Send confirmation link and store returned value if project.sendotp: hashes = sender.send_confirmation_link(new_comment['email'], project.name) setattr(t_comment, "confirmation", hashes[0]) setattr(t_comment, "deletion", hashes[1]) db.session.commit() except exc.IntegrityError as e: # Comment body exists, because content is unique print( f"Duplicate from {request.environ['REMOTE_ADDR']}, error is:\n{e}", file=stderr) return make_response(jsonify(status="post-duplicate"), 400) except Exception: # must be at bottom return make_response(jsonify(status="post-internal-server-error"), 400) export_location(t_comment.location_id) return make_response( jsonify(status="post-success", comment_id=t_comment.comments_id, sendotp=project.sendotp), 200)
def dashboard_review_spam(project: str): """ Shows the manage spam template :param project: The project used for displaying data :return: The template to display for this rouet """ location_id = 0 proj_id = get_id_from_project_name(project) all_locations = db.session.query(TLocation).filter( TLocation.project_id == proj_id).all() # Check if there is a comment, otherwise don't show on management page # This can happen when the last comment was deleted, the location # won't be removed. tmp_list = list() for each in all_locations: comment_count = db.session.query(TComments.comments_id) \ .filter(TComments.location_id == each.id_location) \ .filter(TComments.is_spam == True) \ .count() if comment_count > 0: tmp_list.append(each) all_locations = tmp_list # Project does not exist, error code is used by Javascript, not Flask if proj_id == -1: return redirect( url_for("bp_dashboard.dashboard_project_list", error=404)) if request.args.get('location'): location_id = request.args.get('location') # no parameters found if location_id is None: return render_template("manage-comments.html", locations=all_locations, selected=location_id, title="Review Spam", action="spam") try: if int(location_id) >= 1: spam_comments = db.session.query(TComments) \ .filter(TComments.project_id == proj_id) \ .filter(TComments.location_id == location_id) \ .filter(TComments.is_spam == True) return render_template("manage-comments.html", locations=all_locations, selected=location_id, spam_comments=spam_comments, project=project, title="Review Spam", action="spam") except ValueError: pass export_location(location_id) return render_template("manage-comments.html", locations=all_locations, selected=location_id, project=project, title="Review Spam", action="spam")