def login(): check = is_acceptable_route(True) if not check[0]: return check[1] assert check[1] is None if is_logged_in(): return redirect('/') # TODO What to do if the user is currently logged in? if request.method == 'POST': login_data = request.json user, message = validate_login_data(login_data) if not user: # This should never happen. response = jsonify(message) response.status_code = 400 return response session['email'] = user.email session['just_logged_in'] = True # TODO Change something so as to see the login state. Menu changes of course. return jsonify('login_success') return render_template( 'login.html', page=md( base_page, { 'pagetitle': 'Login', 'data': 'Please login using email and passphrase given at registration time.', }))
def review_list(): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if is_logged_in(): user = User.query.filter_by(email=session['email']).first() if not user: return render_template( '/general.html', page=md( base_page, { 'pagetitle': 'Review List Failed', 'data': 'Logged in user is not a registered user. This cannot happen.', })) if user.role != Role.reviewer: return render_template( '/general.html', page=md( base_page, { 'pagetitle': 'Review List Failed', 'data': 'Logged in user is not a registered reviewer.', })) # TODO reviewer cannot review proposed proposals (done) but what about being a presenter? proposals = [(p.id, p.title, lead.presenter.name, p.session_type.value, already_reviewed(p, user)) for p in Proposal.query.all() if p.proposer != user for lead in p.proposal_presenters if lead.is_lead] return render_template( '/review_list.html', page=md( base_page, { 'pagetitle': 'List of Proposals', 'data': 'Please click on the proposal you wish to review.', 'proposals': proposals, })) return render_template( 'review_list.html', page=md( base_page, { 'pagetitle': 'Review List Failed', 'data': 'You must be registered, logged in, and a reviewer to review proposals', }))
def register_success_update(): return render_template( 'success.html', page=utils.md( base_page, {'data': ''' Your account details were successful updated. '''}))
def my_proposals(): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if is_logged_in(): user = User.query.filter_by(email=session['email']).first() return render_template('my_proposals.html', page=md(base_page, { 'pagetitle': 'My Proposals', 'data': 'The following are your current proposals. Click on a list entry to review that proposal and possibly change it should you wish to.', 'proposals': [{'title': proposal.title, 'id': proposal.id} for proposal in user.proposals] })) return render_template('general.html', page=md(base_page, { 'pagetitle': 'My Proposals Failure', 'year': year, 'data': 'You must be registered and logged in to discover your current proposals.', }))
def proposal_update_success(): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if 'just_updated' in session: session.pop('just_updated', None) return render_template('general.html', page=md(base_page, { 'pagetitle': 'Proposal Update Successful', 'data': ''' Thank you, you have successfully updated your proposal for the ACCU {} conference! If you need to edit it again you can via the 'My Proposal' menu item. '''.format(year), })) return render_template('general.html', page=md(base_page, { 'pagetitle': 'Update Failed', 'data': 'You must be registered and logged in to submit a proposal.', }))
def next_proposal(id, unreviewed): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if is_logged_in(): user = User.query.filter_by(email=session['email']).first() if user.role != Role.reviewer: return render_template( '/general.html', page=md( base_page, { 'pagetitle': 'Proposal Navigation Failed', 'data': 'Logged in user is not a registered reviewer.', })) if not unreviewed: number_of_proposals = Proposal.query.count() for i in range(id + 1, number_of_proposals + 1): if not _reviewer_is_in_proposal_index(user, i): return jsonify(i) response = jsonify("Requested proposal does not exist.") response.status_code = 400 return response i = id + 1 while True: proposal = Proposal.query.filter_by(id=i).first() if not proposal: break if not already_reviewed(proposal, user): if not _reviewer_is_in_proposal(user, proposal): return jsonify(i) i += 1 response = jsonify("Requested proposal does not exist.") response.status_code = 400 return response return render_template( 'general.html', page=md( base_page, { 'pagetitle': 'Proposal Navigation Failed', 'data': 'You must be registered, logged in, and a reviewer to review a proposal', }))
def registration_update(): check = utils.is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if not utils.is_logged_in(): return redirect('/') user = User.query.filter_by(email=session['email']).first() if request.method == 'POST': registration_data = request.json status, message = validate_registration_data(registration_data) if not status: # NB This should never be executed. response = jsonify(message) response.status_code = 400 return response for field in registration_data.keys(): if field == 'passphrase': if registration_data['passphrase']: user.passphrase = utils.hash_passphrase( registration_data['passphrase']) elif field in user.__dict__ and user.__dict__[ field] != registration_data[field]: user.__dict__[field] = registration_data[field] db.session.commit() session['just_updated_register'] = True return jsonify('registration_update_success') return render_template('register.html', page=utils.md( base_page, { 'pagetitle': 'Registration Details Updating', 'data': Markup(''' Here you can edit your registration information. </p> <p> If you do not wish to make any changes just navigate away from this page. There is no specific button for "leave things as they are" that is the default action. (Or rather inaction.) '''), 'email': user.email, 'name': user.name, 'phone': user.phone, 'country': user.country, 'submit_button': 'Save', 'passphrase_required': 'false', 'countries': sorted(countries), }))
def register_success_new(): return render_template("success.html", page=utils.md( base_page, { 'data': ''' You have successfully registered for submitting proposals for the ACCU Conf. Please login and start preparing your proposal for the conference. ''' }))
def register(): check = utils.is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if utils.is_logged_in(): return redirect('/') if request.method == 'POST': registration_data = request.json status, message = validate_registration_data(registration_data) if not status: # NB This should never be executed. response = jsonify(message) response.status_code = 400 return response if not registration_data['passphrase']: # NB This should never be executed. response = jsonify('No passphrase for new registration.') response.status_code = 400 return response if User.query.filter_by(email=registration_data['email']).first(): # Currently this can happen as client-site checking is not implemented. # TODO implement client side checking so this becomes redundant. response = jsonify('The email address is already in use.') response.status_code = 400 return response registration_data['passphrase'] = utils.hash_passphrase( registration_data['passphrase']) db.session.add(User(**registration_data)) db.session.commit() session['just_registered'] = True return jsonify('register_success') default_country = 'United Kingdom' assert default_country in countries return render_template( 'register.html', page=utils.md( base_page, { 'pagetitle': 'Register', 'data': 'Register here for submitting proposals to the ACCU {} Conference' .format(year), 'submit_button': 'Register', 'passphrase_required': 'true', 'country': default_country, 'countries': sorted(countries), }))
def login(): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None # TODO What to do if the user is currently logged in? page = { 'type': 'Login', 'year': year, } if request.method == 'POST': login_data = request.json user, message = validate_login_data(login_data) if not user: return render_template('failure.html', page=md(page, {'data': message})) session['email'] = user.email # TODO Change something so as to see the login state. Menu changes of course. return render_template('success.html', page=md(page, {'data': 'Login successful.'})) else: return render_template('login.html', page=page)
def login_success(): check = is_acceptable_route(True) if not check[0]: return check[1] assert check[1] is None if 'just_logged_in' not in session: return redirect('/') session.pop('just_logged_in', None) if is_logged_in(): return render_template('general.html', page=md( base_page, { 'pagetitle': 'Login Successful', 'data': Markup(''' Login successful. </p> <p> The menu on the left should now show entries for submitting a new proposal, amending the registration details for the logged in user, listing the previously submitted proposals, or logging out. </p> <p> if you have not previously submitted a proposal the "My Proposals" list will be empty. Once you have submitted one or more proposals, they can be amended via the "My Proposals" list. '''), })) return render_template( 'login.html', page=md( base_page, { 'pagetitle': 'Login Failure', 'data': 'Please login using email and passphrase given at registration time.', }))
def registration_update_success(): check = utils.is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if 'just_updated_register' not in session: return redirect('/') session.pop('just_updated_registration', False) if not utils.is_logged_in(): return redirect('/') return render_template( 'general.html', page=utils.md( base_page, { 'pagetitle': 'Registration Update Successful', 'data': 'Your registration details were successfully updated.', }))
def register_success(): check = utils.is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if 'just_registered' not in session: return redirect('/') session.pop('just_registered', None) return render_template("general.html", page=utils.md( base_page, { 'pagetitle': 'Registration Successful', 'data': Markup(''' You have successfully registered for submitting proposals for the ACCU Conference. </p> </p> Please login and start preparing your proposal for the conference. ''') }))
def review_proposal(id): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if is_logged_in(): reviewer = User.query.filter_by(email=session['email']).first() if request.method == 'POST': review_data = request.json if not reviewer: response = jsonify( 'Logged in person is not a reviewer. This cannot happen.') response.status_code = 400 return response proposal = Proposal.query.filter_by(id=id).first() if not proposal: response = jsonify( 'Proposal cannot be found. This cannot happen.') response.status_code = 400 return response # TODO Is this the right way of doing this? score = Score.query.filter_by(proposal=proposal, scorer=reviewer).all() if score: assert len(score) == 1 score[0].score = review_data['score'] else: db.session.add(Score(proposal, reviewer, review_data['score'])) if review_data['comment_for_proposer']: comment = CommentForProposer.query.filter_by( proposal=proposal, commenter=reviewer).all() if comment: comment[0].comment = review_data['comment_for_proposer'] else: db.session.add( CommentForProposer( proposal, reviewer, review_data['comment_for_proposer'])) if review_data['comment_for_committee']: comment = CommentForCommittee.query.filter_by( proposal=proposal, commenter=reviewer).all() if comment: comment[0].comment = review_data['comment_for_committee'] else: db.session.add( CommentForCommittee( proposal, reviewer, review_data['comment_for_committee'])) db.session.commit() return jsonify('Review stored.') if not reviewer: return render_template( '/general.html', page=md( base_page, { 'pagetitle': 'Review Proposal Failed', 'data': 'Logged in user is not a registered user. This cannot happen.', })) if reviewer.role != Role.reviewer: return render_template( '/general.html', page=md( base_page, { 'pagetitle': 'Review Proposal Failed', 'data': 'Logged in user is not a registered reviewer.', })) number_of_proposals = Proposal.query.count() if not (1 <= id <= number_of_proposals): return render_template( 'general.html', page=md( base_page, { 'pagetitle': 'Review Proposal Failed', 'data': 'Requested proposal does not exist.', })) proposal = Proposal.query.filter_by(id=id).first() presenters = [{ 'name': p.name, 'bio': p.bio } for p in proposal.presenters] score = '' comment_for_proposer = '' comment_for_committee = '' if already_reviewed(proposal, reviewer): scores = [s for s in reviewer.scores if s.proposal == proposal] assert len(scores) == 1 score = scores[0].score comments_for_proposer = [ c for c in reviewer.comments_for_proposer if c.proposal == proposal ] if comments_for_proposer: comment_for_proposer = comments_for_proposer[0].comment comments_for_committee = [ c for c in reviewer.comments_for_committee if c.proposal == proposal ] if comments_for_committee: comment_for_committee = comments_for_committee[0].comment has_next = id < number_of_proposals if has_next: for i in range(id + 1, number_of_proposals + 1): if not _reviewer_is_in_proposal_index(reviewer, i): break else: has_next = False has_previous = id > 1 if has_previous: for i in range(id - 1, 0, -1): if not _reviewer_is_in_proposal_index(reviewer, i): break else: has_previous = False return render_template( '/review_proposal.html', page=md( base_page, { 'pagetitle': 'Proposal to Review', 'data': 'There is no specific "do nothing" button, to not do anything simply navigate away from this page.', 'proposal_id': id, 'title': proposal.title, 'summary': proposal.summary, 'session_type': sessiontype_descriptions[proposal.session_type], 'audience': proposal.audience.value, 'notes': proposal.notes, 'presenters': presenters, 'button_label': 'Submit' if not score else 'Update', 'score': score, 'comment_for_proposer': comment_for_proposer, 'comment_for_committee': comment_for_committee, 'has_previous': has_previous, 'has_next': has_next, })) return render_template( 'general.html', page=md( base_page, { 'pagetitle': 'Review Proposal Failed', 'data': 'You must be registered, logged in, and a reviewer to review a proposal', }))
def proposal_update(id): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if is_logged_in(): if request.method == 'POST': user = User.query.filter_by(email=session['email']).first() if user: proposal_data = request.json status, message = validate_proposal_data(proposal_data) if not status: # NB This should never be executed. response = jsonify(message) response.status_code = 400 return response proposal = Proposal.query.filter_by(id=id).first() changeset = {} for item in ('title', 'summary', 'session_type', 'keywords', 'no_video', 'audience', 'notes', 'constraints'): if item in proposal_data: if item == 'session_type': datum = SessionType(proposal_data[item]) elif item == 'audience': datum = SessionAudience(proposal_data[item]) else: datum = proposal_data[item] if datum != proposal.__dict__[item]: changeset[item] = datum if changeset: Proposal.query.filter_by(id=id).update(changeset) assert len(proposal.presenters) == len(proposal_data['presenters']) # TODO What about changing of lead? for i, presenter in enumerate(proposal.presenters): changeset = {} presenters_data = proposal_data['presenters'][i] for item in ('email', 'name', 'bio', 'country'): if item in presenters_data and presenter.__dict__[item] != presenters_data[item]: changeset[item] = presenters_data[item] if changeset: Presenter.query.filter_by(email=proposal.presenters[i].email).update(changeset) db.session.commit() if proposal.scores: for score in proposal.scores: send_email_to( score.scorer.email, score.scorer.name, 'ACCUConf Proposal {} has been updated'.format(proposal.title), ''' An email to let you know that the ACCUConf proposal: {} has been updated by the submitter and you have already scored that proposal. '''.format(proposal.title) ) session['just_updated'] = True return jsonify('proposal_update_success') return render_template('general.html', page=md(base_page, { 'pagetitle': 'Proposal Update POST Error', 'data': 'The logged in user is not in database. This cannot happen.', })) proposal = Proposal.query.filter_by(id=id).first() proposal_presenter = ProposalPresenter.query.filter_by(proposal=proposal).first() if not proposal: return render_template('general.html', page=md(base_page, { 'pagetitle': 'Proposal Not Found', 'data': 'The requested proposal cannot be found.' })) # TODO How to deal with multi-presenter proposals? presenter = proposal.presenters[0] return render_template('submit.html', page=md(base_page, { 'pagetitle': 'Update a proposal', 'data': Markup(submit_form_preface_markup + ''' </p> <p> This page should present all the data of the submission using editable fields. If you wish to change anything amend the field as needed and click Update. </p> <p> If you do not wish to make any changes just navigate away from this page. There is no specific button for "leave things as they are" that is the default action. (Or rather inaction.) '''), 'title': proposal.title, 'session_type': proposal.session_type.value, 'summary': proposal.summary, 'audience': proposal.audience.value, 'keywords': proposal.keywords, 'no_video': proposal.no_video, 'notes': proposal.notes, 'constraints': proposal.constraints, 'presenter': { 'email': presenter.email, 'name': presenter.name, 'is_lead': proposal_presenter.is_lead, 'bio': presenter.bio, 'country': presenter.country, }, 'countries': sorted(countries), 'submit_label': 'Update', 'proposal_id': id, })) return render_template('general.html', page=md(base_page, { 'pagetitle': 'Proposal Update Failure', 'data': 'You must be registered and logged in to update a proposal.', }))
def register(): check = utils.is_acceptable_route() if not check[0]: return check[1] assert check[1] is None user = User.query.filter_by( email=session['email']).first() if utils.is_logged_in() else None edit_mode = bool(user) if request.method == 'POST': registration_data = request.json status, message = validate_registration_data(registration_data) if not status: # NB This should never be executed. response = jsonify(message) response.status_code = 400 return response if not edit_mode: if not registration_data['passphrase']: # NB This should never be executed. response = jsonify('No passphrase for new registration.') response.status_code = 400 return response if User.query.filter_by(email=registration_data['email']).first(): # Currently this can happen as client-site checking is not implemented. # TODO implement client side checking so this becomes redundant. response = jsonify('The email address is already in use.') response.status_code = 400 return response if registration_data['passphrase']: registration_data['passphrase'] = utils.hash_passphrase( registration_data['passphrase']) if edit_mode: User.query.filter_by( email=registration_data['email']).update(registration_data) db.session.commit() return jsonify('register_success_update') db.session.add(User(**registration_data)) db.session.commit() return jsonify('register_success_new') else: return render_template( 'register.html', page=utils.md( base_page, { 'email': user.email if edit_mode else '', 'name': user.name if edit_mode else '', 'phone': user.phone if edit_mode else '', 'street_address': user.street_address if edit_mode else '', 'town_city': user.town_city if edit_mode else '', 'state': user.state if edit_mode else '', 'postal_code': user.postal_code if edit_mode else '', 'country': user.country if edit_mode else 'GBR', # UK shall be the default 'title': 'Account Information' if edit_mode else 'Register', 'data': 'Here you can edit your account information' if edit_mode else 'Register here for submitting proposals to ACCU Conference', 'submit_button': 'Save' if edit_mode else 'Register', 'countries': sorted(list(countries.keys())), }))
def index(): page = { 'pagetitle': 'Call for Proposals', 'year': year, } if app.config['MAINTENANCE']: return render_template('general.html', page=md( page, { 'data': ''' The ACCU {} proposal submission Web application is currently undergoing maintenance. This should not take long, so please come back soon. '''.format(year) })) if app.config['CALL_OPEN']: return render_template('general.html', page=md( page, { 'data': Markup(''' The ACCU {} Call for Proposals is open for business. </p> <i> <p> This Web application is just for submitting proposals, the <a href="https://conference.accu.org">main website</a> is where to go to get information about the conference. </p> <p> There are two blog posts that might be particularly interesting for submitters: </p> <ul> <li> <a href="https://conference.accu.org/news/2017/201710150748_proposalsforaccu2018.html">Proposals for ACCU 2018</a> </li> <li> <a href="https://conference.accu.org/news/2017/201710150836_whatsaccuabout.html">What's ACCU About</a> </li> </ul> <p> NB The text in the summary text box of the submission form will be treated as AsciiDoc source, so please feel free to use AsciiDoc markup in the text entry box. For accepted proposals this text is rendered and will appear on the website and in the booklet. The notes to the committee text box is also treated as AsciiDoc text but is not published except to the conference committee. Other text entries are plain text. All text is assumed to be UTF-8 encoded Unicode. </p> </i> <p> Using the menu items on the left, you can register, if you are not already registered, or login if you are already registered – you have to have registered in order to login. </p> <p> You will have to click one of them to do more than look at this screen. :-) '''.format(year)) })) return render_template('general.html', page=md( page, { 'data': ''' The ACCU {} Call for Proposals is not open. '''.format(year) }))
def submit(): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None if is_logged_in(): if request.method == 'POST': user = User.query.filter_by(email=session['email']).first() if user: proposal_data = request.json status, message = validate_proposal_data(proposal_data) if not status: # NB This should never be executed. response = jsonify(message) response.status_code = 400 return response proposal = Proposal( user, proposal_data.get('title').strip(), proposal_data.get('summary').strip(), SessionType(proposal_data.get('session_type').strip()), SessionAudience(proposal_data.get('audience').strip()) if proposal_data.get('audience') else SessionAudience.all, proposal_data.get('keywords').strip() if proposal_data.get('keywords') else '', proposal_data.get('no_video') if proposal_data.get('no_video') else False, proposal_data.get('notes').strip() if proposal_data.get('notes') else '', proposal_data.get('constraints').strip() if proposal_data.get('constraints') else '', ) db.session.add(proposal) presenters_data = proposal_data.get('presenters') for presenter_data in presenters_data: presenter = Presenter.query.filter_by(email=presenter_data['email']).all() if presenter: assert len(presenter) == 1 presenter = presenter[0] if presenter.name != presenter_data['name']: presenter.name = presenter_data['name'] if presenter.bio != presenter_data['bio']: presenter.bio = presenter_data['bio'] if presenter.country != presenter_data['country']: presenter.country = presenter_data['country'] else: presenter = Presenter( presenter_data['email'], presenter_data['name'], presenter_data['bio'], presenter_data['country'], ) db.session.add(presenter) ProposalPresenter(proposal, presenter, presenter_data['is_lead']) db.session.commit() session['just_submitted'] = True return jsonify('submit_success') return render_template('general.html', page=md(base_page, { 'pagetitle': 'Submit POST Error', 'data': 'The logged in user is not in database. This cannot happen.', })) user = User.query.filter_by(email=session['email']).first() if user: presenter = Presenter.query.filter_by(email=user.email).all() if presenter: assert len(presenter) == 1 presenter = presenter[0] (p_email, p_name, p_bio, p_country) = (presenter.email, presenter.name, presenter.bio, presenter.country) else: (p_email, p_name, p_bio, p_country) = (user.email, user.name, '', user.country) return render_template('submit.html', page=md(base_page, { 'pagetitle': 'Submit a proposal', 'data': Markup(submit_form_preface_markup), 'title': '', 'session_type': SessionType.session.value, 'summary': '', 'audience': SessionAudience.all.value, 'keywords': '', 'no_video': False, 'notes': '', 'constraints': '', 'presenter': { 'email': p_email, 'name': p_name, 'is_lead': True, 'bio': p_bio, 'country': p_country, }, 'countries': sorted(countries), 'submit_label': 'Submit', })) return render_template('general.html', page=md(base_page, { 'pagetitle': 'Submission Problem', 'data': 'The logged in user is not in database. This cannot happen.', })) return render_template('general.html', page=md(base_page, { 'pagetitle': 'Submit Not Possible', 'data': 'You must be registered and logged in to submit a proposal.' }))
def test_md_works(a, b, r): assert utils.md(a, b) == r
def submit(): check = is_acceptable_route() if not check[0]: return check[1] assert check[1] is None page = { 'title': 'Submit', 'year': year, } if is_logged_in(): if request.method == 'POST': user = User.query.filter_by(email=session['email']).first() if user: proposal_data = request.json status, message = validate_proposal_data(proposal_data) response = {} if status: proposal = Proposal( user, proposal_data.get('title').strip(), SessionType(proposal_data.get('session_type')), proposal_data.get('abstract').strip()) db.session.add(proposal) presenters_data = proposal_data.get('presenters') for presenter_data in presenters_data: presenter = Presenter( presenter_data['email'], presenter_data['name'], 'A human being.', presenter_data['country'], presenter_data['state'], ) ProposalPresenter(proposal, presenter, presenter_data['lead']) db.session.add(presenter) db.session.commit() response['success'] = True response[ 'message'] = '''Thank you, you have successfully submitted a proposal for the ACCU {} conference! If you need to edit it you can via the 'My Proposal' menu item.'''.format(year) response['redirect'] = '/' else: response['success'] = False response['message'] = message return jsonify(**response) else: user = User.query.filter_by(email=session['email']).first() if user: return render_template( 'submit.html', page={ 'title': 'Submit a proposal for ACCU {}'.format(year), 'name': user.name, 'proposer': { 'email': user.email, 'name': user.name, 'bio': 'A human being.', 'country': user.country, 'state': user.state, } }) return render_template( 'failure.html', page=md(page, {'data': 'Must be logged in to submit a proposal.'}))