def contact_admin(): """ Contact Admin - This can allow anonymous users to post spam, so for them, I'll add some "poor man's captcha" """ view_info = {} view_info['errors'] = [] captcha = stackhelper.gen_pwd() view_info['anon_captcha'] = captcha view_info['anon_captcha_base64'] = base64.standard_b64encode(captcha) req = request.vars if req.form_submitted: if req.send_b: if req.subject and req.message: if auth_user.is_auth() or\ (not auth_user.is_auth() and\ base64.standard_b64encode(req.captcha_response) == req.c): db.admin_messages.insert( auth_user_id=auth_user.get_user_id(), subject=parse_content(req.subject), message=parse_content(req.message), creation_date=request.now, read_flag=False) redirect(URL(r=request, c='default', f='index')) else: view_info['errors'].append( 'Invalid humanity challenge response, please try ' 'again') return dict(request=request, view_info=view_info) else: view_info['errors'].append( 'Both Subject and Message are required fields') return dict(request=request, view_info=view_info) else: redirect(URL(r=request, c='default', f='index')) else: return dict(request=request, view_info=view_info)
def edit_user(): view_info = {} view_info['errors'] = [] view_info['props'] = {} req = request.vars user_id = request.args[0] # /admin/edit_user/1000 admin_username = auth_user.get_user_name() admin_user_id = auth_user.get_user_id() # roles will be used in the page roles = db().select(db.auth_roles.ALL, orderby=db.auth_roles.role_min_score) # To get the selected user username (located in member_properties) # I will query the table directly username = db(db.auth_users.id == user_id).select( db.auth_users.auth_alias)[0].auth_alias #username = db( # (db.member_properties_skel.property_name=='m_display_name') & # (db.member_properties_skel.id==db.member_properties.property_id) & # (db.member_properties.auth_user==user_id)).select( # db.member_properties.property_value)[0].property_value user_role_info = db((db.auth_users.auth_role_id == db.auth_roles.id) & (db.auth_users.id == user_id)).select( db.auth_roles.role_name, db.auth_roles.id, db.auth_roles.color_designation)[0] view_info['props'].update({ 'user_role_name': user_role_info.role_name, 'user_role_color': user_role_info.color_designation }) user_email = username # Avatar Restrictions (px) - Maybe we need to make these dynamic?? AVATAR_MAX_HEIGHT = 120 AVATAR_MAX_WIDTH = 100 AVATAR_MAX_SIZE = 111213 # Bytes view_info['props'].update({ 'questions': stackhelper.get_member_property('m_questions', user_id, '0') }) view_info['props'].update({ 'real_name': stackhelper.get_member_property('m_real_name', user_id, '') }) view_info['props'].update({ 'web_page': stackhelper.get_member_property('m_web_page', user_id, '') }) view_info['props'].update( {'country': stackhelper.get_member_property('m_country', user_id, '')}) view_info['props'].update( {'locale': stackhelper.get_member_property('m_locale', user_id, '')}) view_info['props'].update({ 'display_name': stackhelper.get_member_property('m_display_name', user_id, '') }) view_info['props'].update({ 'answers': stackhelper.get_member_property('m_answers', user_id, '0') }) view_info['props'].update({ 'comments': stackhelper.get_member_property('m_comments', user_id, '0') }) view_info['props'].update({ 'second_email': stackhelper.get_member_property('m_email', user_id, '') }) view_info['props'].update({ 'points_up': stackhelper.get_member_property('m_points_up', user_id, '0') }) view_info['props'].update({ 'points_dn': stackhelper.get_member_property('m_points_dn', user_id, '0') }) question_subscriptions = db( (db.question_subscriptions.auth_user_id == user_id) & (db.question_subscriptions.is_active == True) & (db.questions.id == db.question_subscriptions.question_id)).select( db.questions.id, db.questions.title) if req.form_submitted: if req.update_b: # Was a change in roles requested? if int(req.new_role) != user_role_info.id: # Yes, then change it db(db.auth_users.id == user_id).update( auth_role_id=req.new_role) # Standard Properties stackhelper.put_member_property('m_real_name', user_id, req.real_name) stackhelper.put_member_property('m_web_page', user_id, req.web_page) stackhelper.put_member_property('m_country', user_id, req.country) stackhelper.put_member_property('m_display_name', user_id, req.display_name) stackhelper.put_member_property('m_email', user_id, req.second_email) # Question Subscriptions remove_questions_subscription = req.remove_questions_subscription if remove_questions_subscription: #raise ValueError, remove_question_subscriptions stackhelper.del_question_subscription( remove_questions_subscription, user_id) # Password Changes if req.new_passwd or req.new_passwd_confirm: if req.new_passwd == req.new_passwd_confirm: # Probably need to offset this to its own security class, # So far there are several (few however) places where I # perform security updates. hash_passwd = hashlib.sha1( '%s%s' % (user_email, req.new_passwd)).hexdigest() db(db.auth_users.auth_alias == user_email).update( auth_passwd=hash_passwd) else: view_info['errors'].append('Password and confirmation do ' 'not match, please try again') # Avatars if req.remove_avatar: db(db.member_avatars.auth_user_id == user_id).update( avatar_active=False) # Crude verification of a FileUpload object set try: filename = req.avatar_data.filename except AttributeError: filename = None if filename: # Resource: # http://epydoc.sourceforge.net/stdlib/ [cont'd next line] # cgi.FieldStorage-class.html image_data = req.avatar_data.file.read() content_type = req.avatar_data.type # "image/png" doc_type, ext = content_type.split('/') if doc_type == 'image': c_type, width, height = \ stackhelper.get_image_info(image_data) update_avatar = True if height > AVATAR_MAX_HEIGHT or width > AVATAR_MAX_WIDTH: view_info['errors'].append( 'Image dimensions exceed the ' 'limits set by the ' 'administrator: ' '(W:%spx, H:%spx)' % (width, height)) view_info['errors'].append( 'Limits are ' '(W:%dpx, H:%dpx)' % (AVATAR_MAX_WIDTH, AVATAR_MAX_HEIGHT)) update_avatar = False if len(image_data) > AVATAR_MAX_SIZE: view_info['errors'].append( 'Avatar exceeds the maximum image size set by the ' 'administrator: %s bytes' % (len(image_data))) view_info['errors'].append('Limit is: (%d bytes)' % (AVATAR_MAX_SIZE)) update_avatar = False if update_avatar: if stackhelper.has_member_avatar(user_id, bypass=False): # Update: db(db.member_avatars.auth_user_id == user_id).update(content_type=content_type, avatar_image=image_data, avatar_active=True) else: # Add: db.member_avatars.insert(content_type=content_type, auth_user_id=user_id, avatar_image=image_data, avatar_active=True) if view_info['errors']: return dict(request=request, view_info=view_info, username=username, user_email=user_email, user_id=user_id, roles=roles, question_subscriptions=question_subscriptions) else: # Save was successful redirect( URL(r=request, c='admin', f='edit_user', args=[user_id], vars=dict(saved=1))) else: # Cancel Requested - back to admin "main" screen redirect(URL(r=request, c='admin', f='users')) else: return dict(request=request, view_info=view_info, username=username, user_email=user_email, user_id=user_id, roles=roles, question_subscriptions=question_subscriptions)
def edit_user(): view_info = {} view_info['errors'] = [] view_info['props'] = {} req = request.vars user_id = request.args[0] # /admin/edit_user/1000 admin_username = auth_user.get_user_name() admin_user_id = auth_user.get_user_id() # roles will be used in the page roles = db().select( db.auth_roles.ALL, orderby=db.auth_roles.role_min_score) # To get the selected user username (located in member_properties) # I will query the table directly username = db( db.auth_users.id==user_id).select( db.auth_users.auth_alias)[0].auth_alias #username = db( # (db.member_properties_skel.property_name=='m_display_name') & # (db.member_properties_skel.id==db.member_properties.property_id) & # (db.member_properties.auth_user==user_id)).select( # db.member_properties.property_value)[0].property_value user_role_info = db( (db.auth_users.auth_role_id==db.auth_roles.id) & (db.auth_users.id==user_id)).select( db.auth_roles.role_name, db.auth_roles.id, db.auth_roles.color_designation)[0] view_info['props'].update({'user_role_name': user_role_info.role_name, 'user_role_color': user_role_info.color_designation}) user_email = username # Avatar Restrictions (px) - Maybe we need to make these dynamic?? AVATAR_MAX_HEIGHT = 120 AVATAR_MAX_WIDTH = 100 AVATAR_MAX_SIZE = 111213 # Bytes view_info['props'].update( {'questions': stackhelper.get_member_property('m_questions', user_id, '0')}) view_info['props'].update( {'real_name': stackhelper.get_member_property('m_real_name', user_id, '')}) view_info['props'].update( {'web_page': stackhelper.get_member_property('m_web_page', user_id, '')}) view_info['props'].update( {'country': stackhelper.get_member_property('m_country', user_id, '')}) view_info['props'].update( {'locale': stackhelper.get_member_property('m_locale', user_id, '')}) view_info['props'].update( {'display_name': stackhelper.get_member_property('m_display_name', user_id, '')}) view_info['props'].update( {'answers': stackhelper.get_member_property('m_answers', user_id, '0')}) view_info['props'].update( {'comments': stackhelper.get_member_property('m_comments', user_id, '0')}) view_info['props'].update( {'second_email': stackhelper.get_member_property('m_email', user_id, '')}) view_info['props'].update( {'points_up': stackhelper.get_member_property('m_points_up', user_id, '0')}) view_info['props'].update( {'points_dn': stackhelper.get_member_property('m_points_dn', user_id, '0')}) question_subscriptions = db( (db.question_subscriptions.auth_user_id==user_id) & (db.question_subscriptions.is_active==True) & (db.questions.id==db.question_subscriptions.question_id)).select( db.questions.id, db.questions.title) if req.form_submitted: if req.update_b: # Was a change in roles requested? if int(req.new_role) != user_role_info.id: # Yes, then change it db(db.auth_users.id==user_id).update( auth_role_id=req.new_role) # Standard Properties stackhelper.put_member_property('m_real_name', user_id, req.real_name) stackhelper.put_member_property('m_web_page', user_id, req.web_page) stackhelper.put_member_property('m_country', user_id, req.country) stackhelper.put_member_property('m_display_name', user_id, req.display_name) stackhelper.put_member_property('m_email', user_id, req.second_email) # Question Subscriptions remove_questions_subscription = req.remove_questions_subscription if remove_questions_subscription: #raise ValueError, remove_question_subscriptions stackhelper.del_question_subscription( remove_questions_subscription, user_id) # Password Changes if req.new_passwd or req.new_passwd_confirm: if req.new_passwd == req.new_passwd_confirm: # Probably need to offset this to its own security class, # So far there are several (few however) places where I # perform security updates. hash_passwd = hashlib.sha1( '%s%s' % (user_email, req.new_passwd)).hexdigest() db(db.auth_users.auth_alias==user_email).update( auth_passwd=hash_passwd) else: view_info['errors'].append('Password and confirmation do ' 'not match, please try again') # Avatars if req.remove_avatar: db(db.member_avatars.auth_user_id==user_id).update( avatar_active=False) # Crude verification of a FileUpload object set try: filename = req.avatar_data.filename except AttributeError: filename = None if filename: # Resource: # http://epydoc.sourceforge.net/stdlib/ [cont'd next line] # cgi.FieldStorage-class.html image_data = req.avatar_data.file.read() content_type = req.avatar_data.type # "image/png" doc_type, ext = content_type.split('/') if doc_type == 'image': c_type, width, height = \ stackhelper.get_image_info(image_data) update_avatar = True if height > AVATAR_MAX_HEIGHT or width > AVATAR_MAX_WIDTH: view_info['errors'].append( 'Image dimensions exceed the ' 'limits set by the ' 'administrator: ' '(W:%spx, H:%spx)' % (width, height)) view_info['errors'].append( 'Limits are ' '(W:%dpx, H:%dpx)' % (AVATAR_MAX_WIDTH, AVATAR_MAX_HEIGHT)) update_avatar = False if len(image_data) > AVATAR_MAX_SIZE: view_info['errors'].append( 'Avatar exceeds the maximum image size set by the ' 'administrator: %s bytes' % (len(image_data))) view_info['errors'].append( 'Limit is: (%d bytes)' % (AVATAR_MAX_SIZE)) update_avatar = False if update_avatar: if stackhelper.has_member_avatar( user_id, bypass=False): # Update: db(db.member_avatars.auth_user_id==user_id).update( content_type=content_type, avatar_image=image_data, avatar_active=True) else: # Add: db.member_avatars.insert(content_type=content_type, auth_user_id=user_id, avatar_image=image_data, avatar_active=True) if view_info['errors']: return dict(request=request, view_info=view_info, username=username, user_email=user_email, user_id=user_id, roles=roles, question_subscriptions=question_subscriptions) else: # Save was successful redirect(URL(r=request, c='admin', f='edit_user', args=[user_id], vars=dict(saved=1))) else: # Cancel Requested - back to admin "main" screen redirect(URL(r=request, c='admin', f='users')) else: return dict(request=request, view_info=view_info, username=username, user_email=user_email, user_id=user_id, roles=roles, question_subscriptions=question_subscriptions)
def index(): """ Main application index (entry point) page """ if session.RUN_ONCE is None: view_info = {} view_info.update({'errors': []}) req = request.vars args = request.args nav_css = 'aquestions' # Some needed system information (think about caching this and # update every 4 hours or so..) num_recs = int( stackhelper.get_system_property('s_questions_per_page', 30)) mode = '' try: offset = int(req.start) except: offset = 0 try: mode = args[0] nav_css = 'a%s' % (mode) except: pass sort_css = 's_dates' if req.sort is None else req.sort # Constraints: # Sort (qsort): # Latest == order by questions.modified_on DESC # Most Voted = order by questions.votes_up DESC # Featured = where questions.is_featured == 'T' # # Type (qtype) # Questions = (no constraints) # Unanswered = where questions.is_answered == 'F' qsort = req.sort # Latest, Most Voted (Sub Tabs) # qtype = req.qtype - Questions, Unanswered (Main Tabs) sql_order = 'questions.modified_on DESC' if qsort == 's_votes': # "most voted" sql_order = 'questions.votes_up DESC' qtype = '' if len(args) > 0: qtype_arg = args[0] if qtype_arg == 'unanswered': qtype = 'u' elif qtype_arg == 'featured': qtype = 'f' elif qtype_arg == 'subscribed': qtype = 's' sql_where = [] extra_tables = [''] # <-- Important if qtype == 'u': # Unanswered sql_where.append("questions.is_answered = 'F'") elif qtype == 'f': # Featured sql_where.append("questions.is_featured = 'T'") elif qtype == 's': # Subscribed sql_where.append("questions.id = " "question_subscriptions.question_id") sql_where.append("question_subscriptions.is_active = 'T'") sql_where.append("question_subscriptions.auth_user_id = " "%s" % (auth_user.get_user_id() or 0)) extra_tables.append('question_subscriptions') # Tag Handling srch_tag = '' tag_table = '' if mode == 'tags': srch_tag = req.get('tag', 'qa-stack') # /default/index/tags?tag=meh # get the "id" of this tag.. sql_tags = db(db.tags.tagname.like('%s%%' % (srch_tag))).select( db.tags.id) tags = ','.join([str(tag.id) for tag in sql_tags]) # '1,5,7,9,etc' sql_where.append('question_tags.question_id = questions.id') sql_where.append('question_tags.tag_id in (%s)' % (tags if tags else 0)) extra_tables.append('question_tags') sql_where_str = '' if sql_where: sql_where_str = "\nand %s" % (' and '.join(sql_where)) # Grab questions sql_cnt = """ select count(questions.id) from questions %s where questions.is_visible='T' %s """ % (','.join(extra_tables), sql_where_str) question_cnt = db.executesql(sql_cnt)[0][0] view_info['question_cnt'] = question_cnt sql = """ select questions.title, questions.created_on, questions.modified_on, questions.views, questions.votes_up, questions.votes_dn, questions.is_answered, questions.is_featured, member_properties.property_value, COUNT(answers.id), auth_roles.role_name, questions.is_closed, questions.id, auth_users.auth_alias, auth_users.id from questions LEFT JOIN answers ON answers.question_id=questions.id, auth_users, member_properties, member_properties_skel, auth_roles %s where questions.is_visible='T' AND member_properties.auth_user=questions.created_by AND member_properties.property_id=member_properties_skel.id AND member_properties_skel.property_name='m_display_name' AND auth_roles.id=auth_users.auth_role_id AND auth_users.id=questions.created_by %s group by questions.id order by %s limit %s offset %s """ % (','.join(extra_tables), sql_where_str, sql_order, num_recs, offset) questions = [] all_questions = db.executesql(sql) if all_questions: for q in all_questions: questions.append({ 'questions.title': q[0], 'questions.created_on': q[1], 'questions.modified_on': q[2], 'questions.views': q[3], 'questions.votes_up': q[4], 'questions.votes_dn': q[5], 'questions.is_answered': (True if q[6] == 'T' else False), 'questions.is_featured': (True if q[7] == 'T' else False), 'member_properties.property_value': q[8], 'answers_id_count': q[9], 'auth_roles.role_name': q[10], 'questions.is_closed': (True if q[11] == 'T' else False), 'questions.id': q[12], 'tags': None, 'auth_users.auth_alias': q[13], 'auth_users.id': q[14] }) # Get tags for questions for q in questions: tags = db((db.questions.id == db.question_tags.question_id) & (db.question_tags.tag_id == db.tags.id) & (db.questions.id == q['questions.id'])).select( db.tags.tagname) #raise ValueError, tags if tags: q['tags'] = tags return dict(view_info=view_info, questions=questions, nav_css=nav_css, sort_css=sort_css) else: # So apparently we have a new system install, redirect to the # appropriate page: redirect(URL(r=request, c='default', f='runonce'))
def view(): """ The default page when viewing a question """ # We need to pull here several important things: Questions, comments for # questions, answers, comments for answers.. view_info = {'errors': []} req = request.vars qid = req.qid if req.qid is not None else request.args[0] # Question ID # Read the question here to see if the user is allowed to access it question = db(db.questions.id == qid).select(db.questions.ALL) user_id = auth_user.get_user_id() if not question or (not question[0].is_visible and not auth_user.is_admin()): # Only admins may see hidden questions.. redirect(URL(r=request, c='default', f='unauthorized')) featured_votes = db((db.score_log.l_type == 'Q') & (db.score_log.subtype == 'featuredrequest') & (db.score_log.qac_id == qid)).count() view_info.update(dict(featured_votes=featured_votes)) offensive_votes = db((db.score_log.l_type == 'Q') & (db.score_log.subtype == 'offensiverequest') & (db.score_log.qac_id == qid)).count() view_info.update(dict(offensive_votes=offensive_votes)) # This controls if the user is subscribed or not to this question view_info['is_subscribed'] = False if auth_user.is_auth(): if stackhelper.user_is_subscribed(qid, user_id): view_info['is_subscribed'] = True # Only the following roles can add comments can_comment = auth_user.has_role('Reviewer,TeamLead,Manager,SysAdmin') view_info['can_comment'] = can_comment if req.form_submitted: view_info['form_submitted'] = True preview_answer = req.preview_answer post_answer = req.post_answer answer = req.get('answer', '').strip() view_info['answer'] = answer if preview_answer is not None: view_info['preview_answer'] = preview_answer else: # Posting an answer to this question here if answer: modified_by = user_id db.answers.insert(question_id=qid, description=answer, created_by=modified_by, created_on=request.now, modified_by=modified_by, is_outstanding=False, votes_up=0, votes_dn=0, is_visible=True, is_answer=False, modified_on=request.now) # Update the original question's last update date/user db(db.questions.id == qid).update(modified_by=modified_by, modified_on=request.now) # Also, increment the number of answers this user has posted stackhelper.increment_member_property('m_answers', modified_by, 1) else: view_info['errors'].append( 'Please add a valid answer to continue') else: # Update the page views for this question, only # if the page is viewed via GET view_rec = db(db.questions.id == qid).select(db.questions.views)[0] db(db.questions.id == qid).update(views=view_rec.views + 1) question = db( (db.questions.id == qid) & (db.questions.created_by == db.member_properties.auth_user) & (db.member_properties.property_id == db.member_properties_skel.id) & (db.member_properties_skel.property_name == 'm_display_name')).select( db.questions.ALL, db.member_properties.property_value)[0] tags = db( (db.questions.id==db.question_tags.question_id) &\ (db.question_tags.tag_id==db.tags.id) &\ (db.questions.id==question.questions.id)).select( db.tags.tagname) q_comments = db( (db.comments.c_type=='Q') & (db.comments.qa_id==qid) & (db.comments.is_visible==True) & (db.comments.created_by==db.member_properties.auth_user) & (db.member_properties.property_id==db.member_properties_skel.id) & (db.member_properties_skel.property_name==\ 'm_display_name')).select(db.comments.ALL, db.member_properties.property_value, orderby=db.comments.modified_on) answers = db( (db.answers.question_id == qid) & (db.answers.is_visible == True) & (db.answers.created_by == db.member_properties.auth_user) & (db.member_properties.property_id == db.member_properties_skel.id) & (db.member_properties_skel.property_name == 'm_display_name')).select( db.answers.ALL, db.member_properties.property_value, orderby=~db.answers.is_answer | ~db.answers.modified_on) # Now every different proposed answer can have comments, # so I need the comments for each answer if applicable) comments_a = {} for answer in answers: comments = db( (db.comments.c_type=='A') & (db.comments.qa_id==answer.answers.id) & (db.comments.is_visible==True) & (db.comments.created_by==db.member_properties.auth_user) & (db.member_properties.property_id==db.member_properties_skel.id) & (db.member_properties_skel.property_name==\ 'm_display_name')).select( db.comments.ALL, db.member_properties.property_value, orderby=db.comments.modified_on) if comments: comments_a.update({answer.answers.id: comments}) return dict(question=question, tags=tags, q_comments=q_comments, answers=answers, comments_a=comments_a, can_comment=can_comment, view_info=view_info)
def index(): """ Main application index (entry point) page """ if session.RUN_ONCE is None: view_info = {} view_info.update({'errors': []}) req = request.vars args = request.args nav_css = 'aquestions' # Some needed system information (think about caching this and # update every 4 hours or so..) num_recs = int( stackhelper.get_system_property('s_questions_per_page', 30)) mode = '' try: offset = int(req.start) except: offset = 0 try: mode = args[0] nav_css = 'a%s' % (mode) except: pass sort_css = 's_dates' if req.sort is None else req.sort # Constraints: # Sort (qsort): # Latest == order by questions.modified_on DESC # Most Voted = order by questions.votes_up DESC # Featured = where questions.is_featured == 'T' # # Type (qtype) # Questions = (no constraints) # Unanswered = where questions.is_answered == 'F' qsort = req.sort # Latest, Most Voted (Sub Tabs) # qtype = req.qtype - Questions, Unanswered (Main Tabs) sql_order = 'questions.modified_on DESC' if qsort == 's_votes': # "most voted" sql_order = 'questions.votes_up DESC' qtype = '' if len(args) > 0: qtype_arg = args[0] if qtype_arg == 'unanswered': qtype = 'u' elif qtype_arg == 'featured': qtype = 'f' elif qtype_arg == 'subscribed': qtype = 's' sql_where = [] extra_tables = [''] # <-- Important if qtype == 'u': # Unanswered sql_where.append("questions.is_answered = 'F'") elif qtype == 'f': # Featured sql_where.append("questions.is_featured = 'T'") elif qtype == 's': # Subscribed sql_where.append("questions.id = " "question_subscriptions.question_id") sql_where.append("question_subscriptions.is_active = 'T'") sql_where.append("question_subscriptions.auth_user_id = " "%s" % (auth_user.get_user_id() or 0)) extra_tables.append('question_subscriptions') # Tag Handling srch_tag = '' tag_table = '' if mode == 'tags': srch_tag = req.get('tag', 'qa-stack') # /default/index/tags?tag=meh # get the "id" of this tag.. sql_tags = db( db.tags.tagname.like('%s%%' % (srch_tag))).select(db.tags.id) tags = ','.join([str(tag.id) for tag in sql_tags]) # '1,5,7,9,etc' sql_where.append('question_tags.question_id = questions.id') sql_where.append('question_tags.tag_id in (%s)' % (tags if tags else 0)) extra_tables.append('question_tags') sql_where_str = '' if sql_where: sql_where_str = "\nand %s" % (' and '.join(sql_where)) # Grab questions sql_cnt = """ select count(questions.id) from questions %s where questions.is_visible='T' %s """ % (','.join(extra_tables), sql_where_str) question_cnt = db.executesql(sql_cnt)[0][0] view_info['question_cnt'] = question_cnt sql = """ select questions.title, questions.created_on, questions.modified_on, questions.views, questions.votes_up, questions.votes_dn, questions.is_answered, questions.is_featured, member_properties.property_value, COUNT(answers.id), auth_roles.role_name, questions.is_closed, questions.id, auth_users.auth_alias, auth_users.id from questions LEFT JOIN answers ON answers.question_id=questions.id, auth_users, member_properties, member_properties_skel, auth_roles %s where questions.is_visible='T' AND member_properties.auth_user=questions.created_by AND member_properties.property_id=member_properties_skel.id AND member_properties_skel.property_name='m_display_name' AND auth_roles.id=auth_users.auth_role_id AND auth_users.id=questions.created_by %s group by questions.id order by %s limit %s offset %s """ % (','.join(extra_tables), sql_where_str, sql_order, num_recs, offset) questions = [] all_questions = db.executesql(sql) if all_questions: for q in all_questions: questions.append({ 'questions.title': q[0], 'questions.created_on': q[1], 'questions.modified_on': q[2], 'questions.views': q[3], 'questions.votes_up': q[4], 'questions.votes_dn': q[5], 'questions.is_answered': (True if q[6] == 'T' else False), 'questions.is_featured': (True if q[7] == 'T' else False), 'member_properties.property_value': q[8], 'answers_id_count': q[9], 'auth_roles.role_name': q[10], 'questions.is_closed': (True if q[11] == 'T' else False), 'questions.id': q[12], 'tags': None, 'auth_users.auth_alias': q[13], 'auth_users.id': q[14]}) # Get tags for questions for q in questions: tags = db( (db.questions.id==db.question_tags.question_id) & (db.question_tags.tag_id==db.tags.id) & (db.questions.id==q['questions.id'])).select( db.tags.tagname) #raise ValueError, tags if tags: q['tags'] = tags return dict(view_info=view_info, questions=questions, nav_css=nav_css, sort_css=sort_css) else: # So apparently we have a new system install, redirect to the # appropriate page: redirect(URL(r=request, c='default', f='runonce'))
def view(): """ The default page when viewing a question """ # We need to pull here several important things: Questions, comments for # questions, answers, comments for answers.. view_info = {'errors': []} req = request.vars qid = req.qid if req.qid is not None else request.args[0] # Question ID # Read the question here to see if the user is allowed to access it question = db(db.questions.id==qid).select(db.questions.ALL) user_id = auth_user.get_user_id() if not question or ( not question[0].is_visible and not auth_user.is_admin()): # Only admins may see hidden questions.. redirect(URL(r=request, c='default', f='unauthorized')) featured_votes = db( (db.score_log.l_type=='Q') & (db.score_log.subtype=='featuredrequest') & (db.score_log.qac_id==qid)).count() view_info.update(dict(featured_votes=featured_votes)) offensive_votes = db( (db.score_log.l_type=='Q') & (db.score_log.subtype=='offensiverequest') & (db.score_log.qac_id==qid)).count() view_info.update(dict(offensive_votes=offensive_votes)) # This controls if the user is subscribed or not to this question view_info['is_subscribed'] = False if auth_user.is_auth(): if stackhelper.user_is_subscribed(qid, user_id): view_info['is_subscribed'] = True # Only the following roles can add comments can_comment = auth_user.has_role('Reviewer,TeamLead,Manager,SysAdmin') view_info['can_comment'] = can_comment if req.form_submitted: view_info['form_submitted'] = True preview_answer = req.preview_answer post_answer = req.post_answer answer = req.get('answer', '').strip() view_info['answer'] = answer if preview_answer is not None: view_info['preview_answer'] = preview_answer else: # Posting an answer to this question here if answer: modified_by = user_id db.answers.insert(question_id=qid, description=answer, created_by=modified_by, created_on=request.now, modified_by=modified_by, is_outstanding=False, votes_up=0, votes_dn=0, is_visible=True, is_answer=False, modified_on=request.now) # Update the original question's last update date/user db(db.questions.id==qid).update(modified_by=modified_by, modified_on=request.now) # Also, increment the number of answers this user has posted stackhelper.increment_member_property('m_answers', modified_by, 1) else: view_info['errors'].append( 'Please add a valid answer to continue') else: # Update the page views for this question, only # if the page is viewed via GET view_rec = db(db.questions.id==qid).select(db.questions.views)[0] db(db.questions.id==qid).update(views=view_rec.views+1) question = db( (db.questions.id==qid) & (db.questions.created_by==db.member_properties.auth_user) & (db.member_properties.property_id==db.member_properties_skel.id) & (db.member_properties_skel.property_name=='m_display_name')).select( db.questions.ALL, db.member_properties.property_value)[0] tags = db( (db.questions.id==db.question_tags.question_id) &\ (db.question_tags.tag_id==db.tags.id) &\ (db.questions.id==question.questions.id)).select( db.tags.tagname) q_comments = db( (db.comments.c_type=='Q') & (db.comments.qa_id==qid) & (db.comments.is_visible==True) & (db.comments.created_by==db.member_properties.auth_user) & (db.member_properties.property_id==db.member_properties_skel.id) & (db.member_properties_skel.property_name==\ 'm_display_name')).select(db.comments.ALL, db.member_properties.property_value, orderby=db.comments.modified_on) answers = db( (db.answers.question_id==qid) & (db.answers.is_visible==True) & (db.answers.created_by==db.member_properties.auth_user) & (db.member_properties.property_id==db.member_properties_skel.id) & (db.member_properties_skel.property_name=='m_display_name')).select( db.answers.ALL, db.member_properties.property_value, orderby=~db.answers.is_answer|~db.answers.modified_on) # Now every different proposed answer can have comments, # so I need the comments for each answer if applicable) comments_a = {} for answer in answers: comments = db( (db.comments.c_type=='A') & (db.comments.qa_id==answer.answers.id) & (db.comments.is_visible==True) & (db.comments.created_by==db.member_properties.auth_user) & (db.member_properties.property_id==db.member_properties_skel.id) & (db.member_properties_skel.property_name==\ 'm_display_name')).select( db.comments.ALL, db.member_properties.property_value, orderby=db.comments.modified_on) if comments: comments_a.update({answer.answers.id: comments}) return dict( question=question, tags=tags, q_comments=q_comments, answers=answers, comments_a=comments_a, can_comment=can_comment, view_info=view_info)