def sublist_read(request): s = request.session r = request p = s['safe_post'] prm = s['safe_params'] sub_title = request.matchdict['sub_title'] dbsession = DBSession() sublist = sublist_queries.get_sublist_by_title(sub_title)[0] if 'new_members' in p and p['new_members'] != '': for l in p['new_members'].splitlines(): sm = SublistMember(sublist_id = sublist.id, member_id = l, added_by = s['users.id']) dbsession.add(sm) if 'op' in prm and prm['op'] == 'del' and 'sid' in prm: #@TODO: make sure user has admin auth to do this s = sublist_queries.remove_sublist_member(prm['sid'], sublist.id) stories = [] #for l in sublist: l = sublist [stories.append(x) for x in sublist_queries.get_sublist_members(l.id)] return {'sublist': sublist, 'stories': stories, 'vote_dict': {}}
def user_info(request): import hashlib import os r = request ses = request.session p = ses['safe_post'] edit_mode = False user_id = None if 'user_id' in r.params: user_id = r.params['user_id'] if 'logged_in' in ses and 'user_id' not in r.params: user_id = ses['users.id'] if 'logged_in' in ses and (user_id == str(ses['users.id']) or queries.get_user_by_id(ses['users.id']).is_user_admin()): edit_mode = True u = queries.get_user_by_id(user_id) if p and edit_mode: dbsession = DBSession() u.about_me = p['about_me'] if r.POST['picture'] != '': orig_filename = r.POST['picture'].filename up_dir = r.registry.settings['user.picture_upload_directory'] u.picture = queries.add_user_picture(orig_filename, str(u.id)[:7], up_dir, r.POST['picture'].file) dbsession.add(u) return {'edit_mode': edit_mode, 'u': u}
def ban(request): r = request s = request.session p = s['safe_post'] if 'logged_in_admin' not in s: return HTTPNotFound() if 'ip' in p: if p['ip'].strip() == '': ip = None else: ip = p['ip'] if p['username'].strip() == '': username = None user_id = None else: username = p['username'] if p['duration'].strip() == 'infinite': duration = None else: duration = "timedelta({0})".format(p['duration']) duration = eval(duration) if username: user_id = queries.get_user_by_name(username).id b = Ban(ip = ip, username = username, duration = duration, user_id = user_id, added_by = s['users.id']) dbsession = DBSession() dbsession.add(b) bans = queries.list_bans() return {'bans': bans}
def story(request): s = request.session r = request p = s['safe_post'] dbsession = DBSession() #@TODO: unify admin-only page handling so that we can easily change this # some day if we want. if 'logged_in_admin' not in s or s['logged_in_admin'] == False: return HTTPNotFound() if 'name' in p and p['name'] != '': name = p['name'].strip() new_sect = Section(name = name, added_by = s['users.id']) dbsession.add(new_sect) s['message'] = "Section {0} successfully added.".format(p['name']) if 'add_pic_button' in p: section = None if 'section_id' in p and p['section_id'] != '': section = section_queries.get_section_by_id(p['section_id']) if section: if r.POST['picture'] != '': orig_filename = r.POST['picture'].filename sp_dir = r.registry.settings['section.picture_upload_directory'] section.picture = section_queries.add_section_picture(orig_filename, str(section.id)[:7], sp_dir, r.POST['picture'].file) dbsession.add(section) sections = section_queries.get_sections() return {'sections': sections}
def save(request): s = request.session p = request.session['safe_params'] u = None op = 'add' vote_dict = {} if 'story_id' in p and 'logged_in' in s: dbsession = DBSession() u = queries.get_user_by_id(s['users.id']) to_save = queries.get_story_by_id(p['story_id']) if 'op' in p: op = p['op'] if op == 'add': if to_save not in u.saved: u.saved.append(to_save) dbsession.add(u) s['message'] = 'Successfully saved {0}'.format(to_save.title) elif op == 'del': if to_save in u.saved: u.saved.remove(to_save) dbsession.add(u) s['message'] = 'Successfully unsaved {0}'.format(to_save.title) elif 'logged_in' in s: u = queries.get_user_by_id(s['users.id']) if u: vds = [] for i in u.saved: vds.append(queries.get_user_votes_on_submission(s['users.id'], i.id)) for vd in vds: if type(vd) == dict: vote_dict.update(vd) return {'saved': u.saved, 'vote_dict': vote_dict, }
def sublist_create(request): s = request.session r = request p = s['safe_post'] dbsession = DBSession() if 'title' in p and p['title'] != '': title = p['title'].strip() description = p['description'] visibility = p['visibility'] new_list = Sublist(title = title, description = description, visibility = visibility, added_by = s['users.id']) dbsession.add(new_list) s['message'] = "Sublist {0} successfully added.".format(p['title']) sublists = sublist_queries.get_sublists() return {'sublists': sublists, 'stories': []}
def vote(request): s = request.session p = request.session["safe_post"] dbsession = DBSession() if "logged_in" in s: way = request.matchdict["way"] if way == "up": points = 1 elif way == "down": points = -1 comment_id = None if "target_type" in p and p["target_type"] == "comment": # the post comes in with comment id in sub_id spot # here, we make sub_id the real sub_id sub_id = queries.get_comment_parent_story(p["sub_id"])[0] comment_id = p["sub_id"] vote_list = ( dbsession.query(Vote).filter(Vote.comment_id == comment_id).filter(Vote.user_id == s["users.id"]).all() ) else: sub_id = p["sub_id"] vote_list = ( dbsession.query(Vote) .filter(Vote.submission_id == p["sub_id"]) .filter(Vote.comment_id == None) .filter(Vote.user_id == s["users.id"]) .all() ) # find out if the user has already voted on this submission if len(vote_list) > 0: if vote_list[0].direction == points: return {"message": "You have already voted on this submission.", "code": "EOLDVOTE", "success": False} else: dbsession.delete(vote_list[0]) v = Vote(sub_id, s["users.id"], points, p["target_type"], comment_id) v.direction = points dbsession = DBSession() dbsession.add(v) return HTTPFound(p["jump_to"]) else: return {"message": "Sorry, you are not logged in.", "code": "ENOLOGIN", "success": False}
def follow(request): s = request.session p = request.session['safe_params'] message = '' if 'logged_in' not in s: s['message'] = 'Sorry, you must be logged in to use the follow feature.' return {'success': False, 'code': 'ENOLOGIN'} if 'follow_id' in p and 'logged_in' in s: dbsession = DBSession() #@TODO: replace with model-wide method to get logged-in user object u = queries.get_user_by_id(s['users.id']) to_follow = queries.get_user_by_id(p['follow_id']) op = 'add' if 'op' in p: op = p['op'] if to_follow not in u.follows and op == 'add': u.follows.append(to_follow) del(s['followed_users']) dbsession.add(u) message = 'Successfully following {0}'.format(to_follow.display_name()) elif to_follow in u.follows and op == 'del': u.follows.remove(to_follow) del(s['followed_users']) dbsession.add(u) message = 'Successfully unfollowed {0}'.format(to_follow.display_name()) elif 'logged_in' in s: u = queries.get_user_by_id(s['users.id']) vds = [] vote_dict = {} if u: for i in u.follows: for story in i.submissions: #@FIXME: this is probably quite slow vds.append(queries.get_user_votes_on_submission(u.id, story.id)) for vd in vds: if type(vd) == dict: vote_dict.update(vd) s['message'] = message return {'follows': u.follows, 'vote_dict': vote_dict}
def story(request): s = request.session r = request p = s['safe_post'] dbsession = DBSession() #@TODO: unify admin-only page handling so that we can easily change this # some day if we want. if 'logged_in_admin' not in s or s['logged_in_admin'] == False: return HTTPNotFound() if 'name' in p and p['name'] != '': name = p['name'].strip() new_sect = Section(name = name, added_by = s['users.id']) dbsession.add(new_sect) s['message'] = "Section {0} successfully added.".format(p['name']) sections = section_queries.get_sections() return {'sections': sections}
def vote(request): s = request.session p = request.session['safe_post'] dbsession = DBSession() if 'logged_in' in s: way = request.matchdict['way'] if way == 'up': points = 1 elif way == 'down': points = -1 comment_id = None if 'target_type' in p and p['target_type'] == 'comment': # the post comes in with comment id in sub_id spot # here, we make sub_id the real sub_id sub_id = submission.get_comment_parent_story(p['sub_id'])[0] comment_id = p['sub_id'] vote_list = dbsession.query(Vote).filter(Vote.comment_id == comment_id).filter(Vote.user_id == s['users.id']).all() else: sub_id = p['sub_id'] vote_list = dbsession.query(Vote).filter(Vote.submission_id == p['sub_id']).filter(Vote.comment_id == None).filter(Vote.user_id == s['users.id']).all() # find out if the user has already voted on this submission if len(vote_list) > 0: if vote_list[0].direction == points: return {'message': 'You have already voted on this submission.', 'code': 'EOLDVOTE', 'success': False} else: dbsession.delete(vote_list[0]) v = Vote(sub_id, s['users.id'], points, p['target_type'], comment_id) v.direction = points dbsession = DBSession() dbsession.add(v) return HTTPFound(p['jump_to']) else: return {'message': 'Sorry, you are not logged in.', 'code': 'ENOLOGIN', 'success': False}
def login(request): #@FIXME: this uses a request handling method with success with which I was experimenting # it is not used elsewhere and is a pain to read and write # success = False causes a page to stop drawing and "error out" # some error conditions therefore don't set success to false because it's more convenient # to draw the rest of the page. # # someone should adapt this to be less success-centric and read less branchy. s = request.session success = True # check for facebook login, provided by Facebook's JS SDK try: fb_cookie = fb.extract_from_cookie(request) try: u = queries.get_user_by_name(fb_cookie['local_username']) except sqlalchemy.orm.exc.NoResultFound: u = fb.create_local_user(fb_cookie['info'], fb_cookie['local_username'], request = request) try: queries.login_user(request, u, None, bypass_password = True) except LoginAdapterExc: pass except LoginAdapterExc: pass if 'logout' in request.session['safe_params']: if 'logged_in' in s: del s['logged_in'] del s['users.id'] if 'u_fbgraph' in s: del s['u_fbgraph'] del s['u_fbinfo'] if 'u_twit' in s: del s['u_twit'] s['message'] = "You have been logged out, thanks." success = True else: s['message'] = "You are not logged in." success = True else: logged_in = False if 'logged_in' in s: s['message'] = "You are already logged in." logged_in = True else: if 'message' not in s: if 'last_login_status' in s: s['message'] = s['last_login_status'] del s['last_login_status'] else: s['message'] = "Please log in." p = request.session['safe_post'] prm = request.session['safe_params'] username = None if 'username' in prm: username = queries.strip_all_html(prm['username']) if p: dbsession = DBSession() if request.session['safe_get']['act'] == 'register': if logged_in: try: u = queries.get_user_by_id(s['users.id']) if u.temporary: queries.create_user(temp_to_perm = True, extant_id = s['users.id'], username = username, password = p['password'], origination = 'site') s['message'] = "Your anonymous profile has been converted, thanks." else: s['message'] = "You can't register while you're logged in." except sqlalchemy.exc.IntegrityError: s['message'] = "This username is already registered, sorry." dbsession.rollback() else: try: queries.create_user(username = username, password = p['password'], origination = 'site') s['message'] = "Successfully registered." success = True except sqlalchemy.exc.IntegrityError: s['message'] = "This username is already registered, sorry." success = False dbsession.rollback() elif request.session['safe_get']['act'] == 'update_pw': if p['new_password'] != p['new_password_confirm']: s['message'] = 'New password doesn\'t match confirmation, please try again.' else: u = queries.get_user_by_id(s['users.id']) if u.verify_pw(p['old_password']): u.password = u.hash_pw(p['new_password']) dbsession.add(u) s['message'] = 'Password updated.' success = True else: s['message'] = 'Old password invalid.' else: try: u = queries.get_user_by_name(username) try: queries.login_user(request, u, p['password']) s['message'] = "Good, logged in" success = True return HTTPFound(request.route_url('post')) except LoginAdapterExc: s['message'] = "Incorrect password." success = False except sqlalchemy.orm.exc.NoResultFound: s['message'] = "Sorry, I don't know you." success = False return {'success': success,}
def submit(request): s = request.session p = request.session['safe_post'] r = request qs = s['safe_get'] s['message'] = "Post a story." dbsession = DBSession() stories = None sections = section_queries.get_sections() new_url_text = '' new_title_text = '' route_name = r.matched_route.name if route_name == 'new_page': # require admin to load a new page form if 'logged_in_admin' not in s or s['logged_in_admin'] == False: return HTTPNotFound() #if uses came in with a share button, redirect to existing discussion if there is one if 'from' in qs and qs['from'] == 'button': existing_post = submission.get_story_by_url_oldest(qs['url']) if existing_post: return HTTPFound(r.route_url('full', sub_id=existing_post.id)) new_url_text = qs['url'] if 'title' in qs: new_title_text = qs['title'] if 'logged_in' not in s: s['message'] = 'Sorry, you must <a href="{0}">log in</a> before you can share a link.'.format( r.route_url('login')) return {'stories': [], 'success': False, 'code': 'ENOLOGIN'} if p and 'title' in p: if 'logged_in' not in s: s['message'] = 'Sorry, please log in first' return {'stories': [], 'success': False, 'code': 'ENOLOGIN'} if 'section_id' not in p or p['section_id'] == '': return {'stories': [], 'success': False, 'code': 'ENOSECTION'} if 'url' in p and p['url'] != '' and p['url'] is not None: p['url'] = general.strip_all_html(p['url']) if not re.match(r'http[s]*:\/\/', p['url']): p['url'] = 'http://' + p['url'] else: # set to None so that NULL goes into the database p['url'] = None if route_name == 'new_page': render_type = p['render_type'] slug = p['slug'] # if we can find this slug already, kill submission here. try: s = dbsession.query(Submission).filter( Submission.slug == slug).one() s['message'] = 'This slug is already taken.' success = False except sqlalchemy.orm.exc.NoResultFound: pass else: slug = '' render_type = 'story_md' if 'section_id' in p: sub = Submission(p['title'][:100], p['description'], p['url'], s['users.id'], section=p['section_id']) else: sub = Submission(p['title'][:100], p['description'], p['url'], s['users.id']) sub.render_type = render_type # slug octet no longer derived from story's actual id if slug == '': slug = u"{title}-{uuid_first_octet}".format( title=slugify.slugify(unicode(p['title'][:100])), uuid_first_octet=str(general.gen_uuid())[:8]) sub.slug = slug dbsession.add(sub) dbsession.flush() # add notify if general.check_notify_default(s['users.id'], r): notify_queries.create_notify(s['users.id'], sub.id, s['users.id']) v = Vote(sub.id, s['users.id'], 1, "submission", None) v.direction = 1 dbsession.add(v) s['message'] = "Added." try: if request.registry.solr_conn: # we flush here to ensure we have a vaild id object when added to solr # we use this if statement so that the exception will be raised before # dbsession is flushed, hence avoiding an unnecessary flush if the site # is not using solr. dbsession.flush() request.registry.solr_conn.add({ 'id': sub.id, 'title': sub.title, 'description': sub.description }) request.registry.solr_conn.commit() except AttributeError: #solr is not configured for this connection pass return HTTPFound(r.route_url('home')) return { 'stories': stories, 'success': True, 'code': 0, 'new_url_text': new_url_text, 'new_title_text': new_title_text, 'sections': sections }
def list(request): from raggregate.queries import user_preference as up s = request.session p = request.session['safe_post'] r = request qs = s['safe_get'] s['message'] = "Post a story." dbsession = DBSession() stories = None filtered_section = None section_found = False sections = section_queries.get_sections() direct_link = False if s.get('users.id', None): direct_link = True if up.get_user_prefs(s['users.id']).get( 'link_to_story', 'off') == 'on' else False if r.params and 'op' in r.params: sub_id = r.params['sub_id'] if r.params['op'] == 'del' or r.params['op'] == 'hide': try: story_to_del = submission.get_story_by_id(sub_id) except sqlalchemy.orm.exc.NoResultFound: story_to_del = None if story_to_del: if users.is_user_allowed_admin_action( s['users.id'], str(story_to_del.id), ): if r.params['op'] == 'del': story_to_del.description = "[deleted]" story_to_del.url = "#" story_to_del.title = "[deleted]" story_to_del.deleted = True dbsession.add(story_to_del) dbsession.flush() else: print("Illegal deletion attempted on {0}".format( story_to_del.submitter.id)) if 'sort.default_order' in r.registry.settings: sort = r.registry.settings['sort.default_order'] else: # default to new sort order if server-specific setting doesn't exist # this should only be the case on old clones; do NOT remove default_order # from the ini just because you want new by default. sort = 'new' page_num = 1 per_page = 30 next_page = None prev_page = None # only pass through approved sort options if 'sort' in qs: if qs['sort'] == 'top': sort = 'top' if qs['sort'] == 'hot': sort = 'hot' if qs['sort'] == 'contro': sort = 'contro' if qs['sort'] == 'new': sort = 'new' if 'page_num' in qs: try: page_num = int(qs['page_num']) except: page_num = 1 if 'section' in qs and qs['section'] == 'all': section = 'all' else: section = None if 'section' in qs and qs['section'] != 'all' and qs['section'] != '': section = qs['section'] try: section = section_queries.get_section_by_name(section) section_found = True except sqlalchemy.orm.exc.NoResultFound: try: section = section_queries.get_section_by_id(section) section_found = True except: from pyramid_tm import transaction transaction.abort() pass # reset section variable to None if we couldn't the named section if section_found == False: section = None else: #if we did find something, set filtered_section so that we can #reference the filtered section in the template. filtered_section = section if 'subscribe' in qs and isinstance(section, Section) and 'logged_in' in s: if qs['subscribe'] == 'y': sub_way = True elif qs['subscribe'] == 'n': sub_way = False sub = sub_queries.create_subscription(s['users.id'], section.id, sub_way) s['message'] = 'Subscription to section {0} updated'.format( section.name) # @FIXME: make per_page configurable in a safe location # it is probably unwise to allow this to be set in the query string # because then a malicious user could say per_page = 10000000000 # and easily launch a DoS via that mechanism. # if 'per_page' in qs: # per_page = qs['per_page'] stories = submission.get_story_list(page_num=page_num, per_page=per_page, sort=sort, request=request, section=section) max_stories = stories['max_stories'] stories = stories['stories'] # this should be split into its own def under queries.py # as it is currently used in at least one other place if max_stories > (page_num * per_page): next_page = page_num + 1 if page_num > 1: prev_page = page_num - 1 vote_dict = {} subscribed_to_list = [] if 'logged_in' in s: vote_dict = users.get_user_votes(s['users.id'], "on_all_submissions") subscribed_to_list = sub_queries.get_subscribed_by_user_id( s['users.id']) for story in stories: #@TODO: Remember to not tally on every load once a real site deploys story.tally_votes() story.tally_comments() print "\n\nsubscribed list: {0}\n\n".format(subscribed_to_list) # Get message of the day motd = motd_queries.get_random_message() return { 'stories': stories, 'success': True, 'code': 0, 'vote_dict': vote_dict, 'max_stories': max_stories, 'prev_page': prev_page, 'next_page': next_page, 'sections': sections, 'filtered_section': section, 'motd': motd, 'subscribed_to_list': subscribed_to_list, 'direct_link': direct_link }
def submit(request): s = request.session p = request.session['safe_post'] r = request qs = s['safe_get'] s['message'] = "Post a story." dbsession = DBSession() stories = None sections = section_queries.get_sections() new_url_text = '' new_title_text = '' route_name = r.matched_route.name if route_name == 'new_page': # require admin to load a new page form if 'logged_in_admin' not in s or s['logged_in_admin'] == False: return HTTPNotFound() #if uses came in with a share button, redirect to existing discussion if there is one if 'from' in qs and qs['from'] == 'button': existing_post = submission.get_story_by_url_oldest(qs['url']) if existing_post: return HTTPFound(r.route_url('full', sub_id=existing_post.id)) new_url_text = qs['url'] if 'title' in qs: new_title_text = qs['title'] if 'logged_in' not in s: s['message'] = 'Sorry, you must <a href="{0}">log in</a> before you can share a link.'.format(r.route_url('login')) return {'stories': [], 'success': False, 'code': 'ENOLOGIN'} if p and 'title' in p: if 'logged_in' not in s: s['message'] = 'Sorry, please log in first' return {'stories': [], 'success': False, 'code': 'ENOLOGIN'} if 'section_id' not in p or p['section_id'] == '': return {'stories': [], 'success': False, 'code': 'ENOSECTION'} if 'url' in p and p['url'] != '' and p['url'] is not None: p['url'] = general.strip_all_html(p['url']) if not re.match(r'http[s]*:\/\/', p['url']): p['url'] = 'http://' + p['url'] else: # set to None so that NULL goes into the database p['url'] = None if route_name == 'new_page': render_type = p['render_type'] slug = p['slug'] # if we can find this slug already, kill submission here. try: s = dbsession.query(Submission).filter(Submission.slug == slug).one() s['message'] = 'This slug is already taken.' success = False except sqlalchemy.orm.exc.NoResultFound: pass else: slug = '' render_type = 'story_md' if 'section_id' in p: sub = Submission(p['title'][:100], p['description'], p['url'], s['users.id'], section = p['section_id']) else: sub = Submission(p['title'][:100], p['description'], p['url'], s['users.id']) sub.render_type = render_type # slug octet no longer derived from story's actual id if slug == '': slug = u"{title}-{uuid_first_octet}".format( title = slugify.slugify(unicode(p['title'][:100])), uuid_first_octet = str(general.gen_uuid())[:8]) sub.slug = slug dbsession.add(sub) dbsession.flush() # add notify if general.check_notify_default(s['users.id'], r): notify_queries.create_notify(s['users.id'], sub.id, s['users.id']) v = Vote(sub.id, s['users.id'], 1, "submission", None) v.direction = 1 dbsession.add(v) s['message'] = "Added." try: if request.registry.solr_conn: # we flush here to ensure we have a vaild id object when added to solr # we use this if statement so that the exception will be raised before # dbsession is flushed, hence avoiding an unnecessary flush if the site # is not using solr. dbsession.flush() request.registry.solr_conn.add({'id': sub.id, 'title': sub.title, 'description': sub.description}) request.registry.solr_conn.commit() except AttributeError: #solr is not configured for this connection pass return HTTPFound(r.route_url('home')) return {'stories': stories, 'success': True, 'code': 0, 'new_url_text': new_url_text, 'new_title_text': new_title_text, 'sections': sections}
def full(request): message = '' #@TODO: Change this to use slugs instead of literal guids sub_id = request.matchdict['sub_id'] sub_id = submission.get_story_id_from_slug(sub_id) dbsession = DBSession() p = request.session['safe_post'] prm = request.session['safe_params'] s = request.session logged_in = False if 'logged_in' in s: #return {'message': 'Sorry, please log in first.', 'story': {}, 'comments': {}, 'success': False, 'code': 'ENOLOGIN'} logged_in = True # record the comment if 'op' in prm and prm['op'] == 'del' and logged_in: if 'comment_id' in prm: c = submission.get_comment_by_id(prm['comment_id']) if users.is_user_allowed_admin_action(s['users.id'], str(c.id), ): c.deleted = True dbsession.add(c) s['message'] = 'Comment deleted.' if 'op' in prm and prm['op'] == 'edit' and logged_in: if 'comment_id' in prm: c = submission.get_comment_by_id(prm['comment_id']) if users.is_user_allowed_admin_action(s['users.id'], str(c.id), ): c.body = prm['body'] dbsession.add(c) s['message'] = 'Comment updated.' else: if 'description-textarea' in request.session['safe_post'] and logged_in: sub = submission.get_story_by_id(sub_id) if users.is_user_allowed_admin_action(s['users.id'], str(sub.id)): sub.description = prm['description-textarea'] dbsession.add(sub) s['message'] = 'Description updated.' if 'body' in request.session['safe_post'] and logged_in: if p['parent_type'] == 'story': in_reply_to = submission.get_story_by_id(p['comment_parent']).submitter.id elif p['parent_type'] == 'comment': c = submission.get_comment_by_id(p['comment_parent']) in_reply_to = c.user_id c = Comment(sub_id, s['users.id'], p['comment_parent'], prm['body'], in_reply_to = in_reply_to) dbsession.add(c) dbsession.flush() # if enabled default, subscribe user to own comment. # @TODO: make a preference for users to toggle this if general.check_notify_default(s['users.id'], request): notify_queries.create_notify(s['users.id'], c.id, s['users.id']) v = Vote(sub_id, s['users.id'], 1, "comment", c.id) v.direction = 1 dbsession.add(v) notify_queries.fire_to_listeners(p['comment_parent'], s['users.id'], c.id, request) s['message'] = 'Comment added.' #@TODO: Stop using SA queries in views, move them to individual models story = submission.get_story_by_id(sub_id) story.tally_votes() story_vote_dict = {} comment_vote_dict = {} if logged_in: # see queries.py; these two should not be separate. #@FIXME story_vote_dict = users.get_user_votes(s['users.id'], "on_submission", sub_id) comment_vote_dict = users.get_user_votes(s['users.id'], "on_submissions_comments", sub_id) page_num = 1 per_page = 30 if 'sort.comment_default_order' in request.registry.settings: sort = request.registry.settings['sort.comment_default_order'] else: # do NOT change the hardcoded default, change in the ini as above sort = 'top' next_page = None prev_page = None if 'comment_sort' in prm: sort = prm['comment_sort'] if 'page_num' in prm: try: page_num = int(prm['page_num']) except: page_num = 1 # comments returns a dict; see queries.py if 'comment_perma' not in prm: comments = submission.get_comments(sub_id, organize_parentage=True, page_num = page_num, per_page = per_page, sort = sort) else: comments = submission.get_comments(sub_id, organize_parentage=True, page_num = page_num, per_page = per_page, sort = sort, target = 'comment', target_id = prm['comment_perma']) for c in comments['comments']: #@TODO: Don't do this on every load on a real deployment c.tally_votes() if c.deleted: c.body = '[deleted]' if page_num > 1: prev_page = page_num - 1 if comments['max_comments'] > (page_num * per_page): next_page = page_num + 1 return {'story': story, 'comments': comments, 'success': True, 'code': 0, 'story_vote_dict': story_vote_dict, 'comment_vote_dict': comment_vote_dict, 'next_page': next_page, 'prev_page': prev_page, 'render_type': story.render_type, }
def list(request): from raggregate.queries import user_preference as up s = request.session p = request.session['safe_post'] r = request qs = s['safe_get'] s['message'] = "Post a story." dbsession = DBSession() stories = None filtered_section = None section_found = False sections = section_queries.get_sections() direct_link = False if s.get('users.id', None): direct_link = True if up.get_user_prefs(s['users.id']).get('link_to_story', 'off') == 'on' else False if r.params and 'op' in r.params: sub_id = r.params['sub_id'] if r.params['op'] == 'del' or r.params['op'] == 'hide': try: story_to_del = submission.get_story_by_id(sub_id) except sqlalchemy.orm.exc.NoResultFound: story_to_del = None if story_to_del: if users.is_user_allowed_admin_action(s['users.id'], str(story_to_del.id), ): if r.params['op'] == 'del': story_to_del.description = "[deleted]" story_to_del.url = "#" story_to_del.title = "[deleted]" story_to_del.deleted = True dbsession.add(story_to_del) dbsession.flush() else: print("Illegal deletion attempted on {0}".format(story_to_del.submitter.id)) if 'sort.default_order' in r.registry.settings: sort = r.registry.settings['sort.default_order'] else: # default to new sort order if server-specific setting doesn't exist # this should only be the case on old clones; do NOT remove default_order # from the ini just because you want new by default. sort = 'new' page_num = 1 per_page = 30 next_page = None prev_page = None # only pass through approved sort options if 'sort' in qs: if qs['sort'] == 'top': sort = 'top' if qs['sort'] == 'hot': sort = 'hot' if qs['sort'] == 'contro': sort = 'contro' if qs['sort'] == 'new': sort = 'new' if 'page_num' in qs: try: page_num = int(qs['page_num']) except: page_num = 1 if 'section' in qs and qs['section'] == 'all': section = 'all' else: section = None if 'section' in qs and qs['section'] != 'all' and qs['section'] != '': section = qs['section'] try: section = section_queries.get_section_by_name(section) section_found = True except sqlalchemy.orm.exc.NoResultFound: try: section = section_queries.get_section_by_id(section) section_found = True except: from pyramid_tm import transaction transaction.abort() pass # reset section variable to None if we couldn't the named section if section_found == False: section = None else: #if we did find something, set filtered_section so that we can #reference the filtered section in the template. filtered_section = section if 'subscribe' in qs and isinstance(section, Section) and 'logged_in' in s: if qs['subscribe'] == 'y': sub_way = True elif qs['subscribe'] == 'n': sub_way = False sub = sub_queries.create_subscription(s['users.id'], section.id, sub_way) s['message'] = 'Subscription to section {0} updated'.format(section.name) # @FIXME: make per_page configurable in a safe location # it is probably unwise to allow this to be set in the query string # because then a malicious user could say per_page = 10000000000 # and easily launch a DoS via that mechanism. # if 'per_page' in qs: # per_page = qs['per_page'] stories = submission.get_story_list(page_num = page_num, per_page = per_page, sort = sort, request = request, section = section) max_stories = stories['max_stories'] stories = stories['stories'] # this should be split into its own def under queries.py # as it is currently used in at least one other place if max_stories > (page_num * per_page): next_page = page_num + 1 if page_num > 1: prev_page = page_num - 1 vote_dict = {} subscribed_to_list = [] if 'logged_in' in s: vote_dict = users.get_user_votes(s['users.id'], "on_all_submissions") subscribed_to_list = sub_queries.get_subscribed_by_user_id(s['users.id']) for story in stories: #@TODO: Remember to not tally on every load once a real site deploys story.tally_votes() story.tally_comments() print "\n\nsubscribed list: {0}\n\n".format(subscribed_to_list) # Get message of the day motd = motd_queries.get_random_message() return {'stories': stories, 'success': True, 'code': 0, 'vote_dict': vote_dict, 'max_stories': max_stories, 'prev_page': prev_page, 'next_page': next_page, 'sections': sections, 'filtered_section': section, 'motd': motd, 'subscribed_to_list': subscribed_to_list, 'direct_link': direct_link}
def post(request): s = request.session p = request.session["safe_post"] r = request qs = s["safe_get"] s["message"] = "Post a story." dbsession = DBSession() stories = None new_url_text = "" new_title_text = "" # if uses came in with a share button, redirect to existing discussion if there is one if "from" in qs and qs["from"] == "button": existing_post = queries.get_story_by_url_oldest(qs["url"]) if existing_post: return HTTPFound(r.route_url("full", sub_id=existing_post.id)) new_url_text = qs["url"] if "title" in qs: new_title_text = qs["title"] if "new_post" in qs and qs["new_post"] == "y": if "logged_in" not in s: s["message"] = 'Sorry, you must <a href="{0}">log in</a> before you can share a link.'.format( r.route_url("login") ) return {"stories": [], "success": False, "code": "ENOLOGIN"} if p and "title" in p: if "logged_in" not in s: s["message"] = "Sorry, please log in first" return {"stories": [], "success": False, "code": "ENOLOGIN"} if p["url"] != "" and p["url"] is not None: p["url"] = queries.strip_all_html(p["url"]) if not re.match(r"http[s]*:\/\/", p["url"]): p["url"] = "http://" + p["url"] else: # set to None so that NULL goes into the database p["url"] = None sub = Submission(p["title"][:100], p["description"], p["url"], s["users.id"]) dbsession.add(sub) dbsession.flush() v = Vote(sub.id, s["users.id"], 1, "submission", None) v.direction = 1 dbsession.add(v) sub.slug = u"{title}-{uuid_first_octet}".format( title=slugify.slugify(unicode(p["title"][:100])), uuid_first_octet=str(sub.id)[:8] ) dbsession.add(sub) s["message"] = "Added." try: if request.registry.solr_conn: # we flush here to ensure we have a vaild id object when added to solr # we use this if statement so that the exception will be raised before # dbsession is flushed, hence avoiding an unnecessary flush if the site # is not using solr. dbsession.flush() request.registry.solr_conn.add({"id": sub.id, "title": sub.title, "description": sub.description}) request.registry.solr_conn.commit() except AttributeError: # solr is not configured for this connection pass if r.params and "op" in r.params: sub_id = r.params["sub_id"] if r.params["op"] == "del": try: story_to_del = queries.get_story_by_id(sub_id) except sqlalchemy.orm.exc.NoResultFound: story_to_del = None if story_to_del: if queries.is_user_allowed_admin_action(s["users.id"], str(story_to_del.id)): story_to_del.description = "[deleted]" story_to_del.url = "#" story_to_del.title = "[deleted]" story_to_del.deleted = True dbsession.add(story_to_del) dbsession.flush() else: print("Illegal deletion attempted on {0}".format(story_to_del.submitter.id)) if "sort.default_order" in r.registry.settings: sort = r.registry.settings["sort.default_order"] else: # default to new sort order if server-specific setting doesn't exist # this should only be the case on old clones; do NOT remove default_order # from the ini just because you want new by default. sort = "new" page_num = 1 per_page = 30 next_page = None prev_page = None # only pass through approved sort options if "sort" in qs: if qs["sort"] == "top": sort = "top" if qs["sort"] == "hot": sort = "hot" if qs["sort"] == "contro": sort = "contro" if qs["sort"] == "new": sort = "new" if "page_num" in qs: try: page_num = int(qs["page_num"]) except: page_num = 1 # @FIXME: make per_page configurable in a safe location # it is probably unwise to allow this to be set in the query string # because then a malicious user could say per_page = 10000000000 # and easily launch a DoS via that mechanism. # if 'per_page' in qs: # per_page = qs['per_page'] stories = queries.get_story_list(page_num=page_num, per_page=per_page, sort=sort, request=request) max_stories = stories["max_stories"] stories = stories["stories"] # this should be split into its own def under queries.py # as it is currently used in at least one other place if max_stories > (page_num * per_page): next_page = page_num + 1 if page_num > 1: prev_page = page_num - 1 vote_dict = {} if "logged_in" in s: vote_dict = queries.get_user_votes_on_all_submissions(s["users.id"]) for s in stories: # @TODO: Remember to not tally on every load once a real site deploys s.tally_votes() s.tally_comments() return { "stories": stories, "success": True, "code": 0, "vote_dict": vote_dict, "max_stories": max_stories, "prev_page": prev_page, "next_page": next_page, "new_url_text": new_url_text, "new_title_text": new_title_text, }
def epistle(request): message = '' dbsession = DBSession() s = request.session p = request.session['safe_post'] if 'logged_in' not in s: s['message'] = 'Sorry, you must be logged in to use the messaging feature.' return {'success': False, 'code': 'ENOLOGIN'} if p and 'recipient' in p: if p['recipient'] == '' and p['recipient-name'] == '': s['message'] = "No recipient provided." return {'code': 'ENORECP', 'success': False} if p['recipient'] == '': # look up recipient-name try: recp = queries.get_user_by_name(p['recipient-name']) except sqlalchemy.orm.exc.NoResultFound: #@TODO: discuss facebook name sending implications s['message'] = "Could not find that user." return {'code': 'ENORECP', 'success': False} else: try: recp = queries.get_user_by_id(p['recipient']) except: s['message'] = "Could not find that user." return {'code': 'ENORECP', 'success': False} if p['subject'] == '': subject = None else: subject = p['subject'] if 'parent_id' not in p or p['parent_id'] == '': parent_id = None parent_type = 'epistle' else: parent_id = p['parent_id'] parent_obj = queries.find_by_id(parent_id) if isinstance(parent_obj, Comment): parent_type = 'comment' c = Comment(parent_obj.submission_id, s['users.id'], parent_obj.id, p['body'], in_reply_to = parent_obj.user_id) dbsession.add(c) else: parent_type = 'reply' if parent_type != 'comment': ep = Epistle(recp.id, s['users.id'], p['body'], parent=parent_id, parent_type=parent_type, subject=subject) dbsession.add(ep) message = 'Message sent.' box = request.matchdict['box'] if box == 'in': comments = queries.get_unread_comments_by_user_id(s['users.id']) elif box == 'comments': comments = queries.get_read_comments_by_user_id(s['users.id']) else: comments = [] if box != 'comments': ep = queries.get_epistle_roots(id=s['users.id'], target=box) epistle_children = {} for e in ep: e_id = str(e.id) epistle_children[e_id] = queries.get_epistle_children(e.id) flat_eps = [] [flat_eps.append(e) for e in _unwrap_list(ep)] [flat_eps.append(e) for e in _unwrap_list(epistle_children.values())] for e in flat_eps: if str(e.recipient) == s['users.id']: queries.mark_epistle_read(e) e = _assign_epistle_parent(e) for c in comments: queries.mark_comment_read(c) else: ep = {} epistle_children = {} return {'epistles': {'roots': ep, 'children': epistle_children}, 'comments': comments, 'success': True, 'code': 0,}
def login(request): #@FIXME: this uses a request handling method with success with which I was experimenting # it is not used elsewhere and is a pain to read and write # success = False causes a page to stop drawing and "error out" # some error conditions therefore don't set success to false because it's more convenient # to draw the rest of the page. # # someone should adapt this to be less success-centric and read less branchy. s = request.session success = True # check for facebook login, provided by Facebook's JS SDK try: fb_cookie = fb.extract_from_cookie(request) try: u = users.get_user_by_name(fb_cookie['local_username']) except sqlalchemy.orm.exc.NoResultFound: u = fb.create_local_user(fb_cookie['info'], fb_cookie['local_username'], request=request) try: users.login_user(request, u, None, bypass_password=True) except LoginAdapterExc: pass except LoginAdapterExc: pass if 'logout' in request.session['safe_params']: if 'logged_in' in s: del s['logged_in'] del s['users.id'] if 'u_fbgraph' in s: del s['u_fbgraph'] del s['u_fbinfo'] if 'u_twit' in s: del s['u_twit'] s['message'] = "You have been logged out, thanks." success = True else: s['message'] = "You are not logged in." success = True else: logged_in = False if 'logged_in' in s: s['message'] = "You are already logged in." logged_in = True else: if 'message' not in s: if 'last_login_status' in s: s['message'] = s['last_login_status'] del s['last_login_status'] else: s['message'] = "Please log in." p = request.session['safe_post'] prm = request.session['safe_params'] username = None if 'username' in prm: username = general.strip_all_html(prm['username']) if p: dbsession = DBSession() if request.session['safe_get']['act'] == 'register': if logged_in: try: u = users.get_user_by_id(s['users.id']) if u.temporary: users.create_user(temp_to_perm=True, extant_id=s['users.id'], username=username, password=p['password'], email=p['email'], origination='site') s['message'] = "Your anonymous profile has been converted, thanks." else: s['message'] = "You can't register while you're logged in." except sqlalchemy.exc.IntegrityError: s['message'] = "This username is already registered, sorry." dbsession.rollback() else: try: users.create_user(username=username, password=p['password'], email=p['email'], origination='site') s['message'] = "Successfully registered." success = True except sqlalchemy.exc.IntegrityError: s['message'] = "This username is already registered, sorry." success = False dbsession.rollback() elif request.session['safe_get']['act'] == 'update_pw': if p['new_password'] != p['new_password_confirm']: s['message'] = 'New password doesn\'t match confirmation, please try again.' else: u = None if s['logged_in_admin']: if 'user_id' in prm: u = users.get_user_by_id(prm['user_id']) if u == None: u = users.get_user_by_id(s['users.id']) if u.verify_pw(p['old_password']) or s['logged_in_admin']: u.password = u.hash_pw(p['new_password']) dbsession.add(u) s['message'] = 'Password updated.' success = True else: s['message'] = 'Old password invalid.' elif request.session['safe_get']['act'] == 'forgot_pass': user = users.get_user_by_email(p['email']) if not user: s['message'] = "That email isn't registered" else: s['message'] = "Check your mail for a confirmation message." users.send_lost_password_verify_email(request, user) else: try: u = users.get_user_by_name(username) try: users.login_user(request, u, p['password']) s['message'] = "Good, logged in" success = True return HTTPFound(request.route_url('post')) except LoginAdapterExc: s['message'] = "Incorrect password." success = False except sqlalchemy.orm.exc.NoResultFound: s['message'] = "Sorry, I don't know you." success = False return { 'success': success, }
def full(request): message = "" # @TODO: Change this to use slugs instead of literal guids sub_id = request.matchdict["sub_id"] sub_id = queries.get_story_id_from_slug(sub_id) dbsession = DBSession() p = request.session["safe_post"] prm = request.session["safe_params"] s = request.session logged_in = False if "logged_in" in s: # return {'message': 'Sorry, please log in first.', 'story': {}, 'comments': {}, 'success': False, 'code': 'ENOLOGIN'} logged_in = True # record the comment if "op" in prm and prm["op"] == "del" and logged_in: if "comment_id" in prm: c = queries.get_comment_by_id(prm["comment_id"]) if queries.is_user_allowed_admin_action(s["users.id"], str(c.id)): c.body = "[deleted]" c.deleted = True dbsession.add(c) s["message"] = "Comment deleted." if "op" in prm and prm["op"] == "edit" and logged_in: if "comment_id" in prm: c = queries.get_comment_by_id(prm["comment_id"]) if queries.is_user_allowed_admin_action(s["users.id"], str(c.id)): c.body = prm["body"] dbsession.add(c) s["message"] = "Comment updated." else: if "description-textarea" in request.session["safe_post"] and logged_in: sub = queries.get_story_by_id(sub_id) if queries.is_user_allowed_admin_action(s["users.id"], str(sub.id)): sub.description = prm["description-textarea"] dbsession.add(sub) s["message"] = "Description updated." if "body" in request.session["safe_post"] and logged_in: if p["parent_type"] == "story": in_reply_to = queries.get_story_by_id(p["comment_parent"]).submitter.id elif p["parent_type"] == "comment": c = queries.get_comment_by_id(p["comment_parent"]) in_reply_to = c.user_id c = Comment(sub_id, s["users.id"], p["comment_parent"], prm["body"], in_reply_to=in_reply_to) dbsession.add(c) dbsession.flush() v = Vote(sub_id, s["users.id"], 1, "comment", c.id) v.direction = 1 dbsession.add(v) s["message"] = "Comment added." # @TODO: Stop using SA queries in views, move them to individual models story = queries.get_story_by_id(sub_id) story.tally_votes() story_vote_dict = {} comment_vote_dict = {} if logged_in: # see queries.py; these two should not be separate. #@FIXME story_vote_dict = queries.get_user_votes_on_submission(s["users.id"], sub_id) comment_vote_dict = queries.get_user_votes_on_submissions_comments(s["users.id"], sub_id) page_num = 1 per_page = 30 if "sort.comment_default_order" in request.registry.settings: sort = request.registry.settings["sort.comment_default_order"] else: # do NOT change the hardcoded default, change in the ini as above sort = "top" next_page = None prev_page = None if "comment_sort" in prm: sort = prm["comment_sort"] if "page_num" in prm: try: page_num = int(prm["page_num"]) except: page_num = 1 # comments returns a dict; see queries.py if "comment_perma" not in prm: comments = queries.get_comments( sub_id, organize_parentage=True, page_num=page_num, per_page=per_page, sort=sort ) else: comments = queries.get_comments( sub_id, organize_parentage=True, page_num=page_num, per_page=per_page, sort=sort, target="comment", target_id=prm["comment_perma"], ) for c in comments["comments"]: # @TODO: Don't do this on every load on a real deployment c.tally_votes() if page_num > 1: prev_page = page_num - 1 if comments["max_comments"] > (page_num * per_page): next_page = page_num + 1 return { "story": story, "comments": comments, "success": True, "code": 0, "story_vote_dict": story_vote_dict, "comment_vote_dict": comment_vote_dict, "next_page": next_page, "prev_page": prev_page, }
def epistle(request): message = '' dbsession = DBSession() s = request.session p = request.session['safe_post'] if 'logged_in' not in s: s['message'] = 'Sorry, you must be logged in to use the messaging feature.' return {'success': False, 'code': 'ENOLOGIN'} if p and 'recipient' in p: if p['recipient'] == '' and p['recipient-name'] == '': s['message'] = "No recipient provided." return {'code': 'ENORECP', 'success': False} if p['recipient'] == '': # look up recipient-name try: recp = users.get_user_by_name(p['recipient-name']) except sqlalchemy.orm.exc.NoResultFound: #@TODO: discuss facebook name sending implications s['message'] = "Could not find that user." return {'code': 'ENORECP', 'success': False} else: try: recp = users.get_user_by_id(p['recipient']) except: s['message'] = "Could not find that user." return {'code': 'ENORECP', 'success': False} if p['subject'] == '': subject = None else: subject = p['subject'] if 'parent_id' not in p or p['parent_id'] == '': parent_id = None parent_type = 'epistle' else: parent_id = p['parent_id'] parent_obj = general.find_by_id(parent_id) if isinstance(parent_obj, Comment): parent_type = 'comment' c = Comment(parent_obj.submission_id, s['users.id'], parent_obj.id, p['body'], in_reply_to=parent_obj.user_id) dbsession.add(c) else: parent_type = 'reply' if parent_type != 'comment': ep = Epistle(recp.id, s['users.id'], p['body'], parent=parent_id, parent_type=parent_type, subject=subject) dbsession.add(ep) message = 'Message sent.' box = request.matchdict['box'] if box == 'in': comments = epistle_queries.get_unread_comments_by_user_id( s['users.id']) elif box == 'comments': comments = epistle_queries.get_read_comments_by_user_id(s['users.id']) else: comments = [] if box != 'comments': ep = epistle_queries.get_epistle_roots(id=s['users.id'], target=box) epistle_children = {} for e in ep: e_id = str(e.id) epistle_children[e_id] = epistle_queries.get_epistle_children(e.id) flat_eps = [] [flat_eps.append(e) for e in _unwrap_list(ep)] [flat_eps.append(e) for e in _unwrap_list(epistle_children.values())] for e in flat_eps: if str(e.recipient) == s['users.id']: epistle_queries.mark_epistle_read(e) e = _assign_epistle_parent(e) for c in comments: epistle_queries.mark_comment_read(c) else: ep = {} epistle_children = {} return { 'epistles': { 'roots': ep, 'children': epistle_children }, 'comments': comments, 'success': True, 'code': 0, }