def register(): """ Register method for creating a PYBOSSA account. Returns a Jinja2 template """ if current_app.config.get('LDAP_HOST', False): return abort(404) form = RegisterForm(request.body) msg = "I accept receiving emails from %s" % current_app.config.get('BRAND') form.consent.label = msg if request.method == 'POST' and form.validate(): account = dict(fullname=form.fullname.data, name=form.name.data, email_addr=form.email_addr.data, password=form.password.data, consent=form.consent.data) confirm_url = get_email_confirmation_url(account) if current_app.config.get('ACCOUNT_CONFIRMATION_DISABLED'): return _create_account(account) msg = dict(subject='Welcome to %s!' % current_app.config.get('BRAND'), recipients=[account['email_addr']], body=render_template('/account/email/validate_account.md', user=account, confirm_url=confirm_url)) msg['html'] = markdown(msg['body']) mail_queue.enqueue(send_mail, msg) data = dict(template='account/account_validation.html', title=gettext("Account validation"), status='sent') return handle_content_type(data) if request.method == 'POST' and not form.validate(): flash(gettext('Please correct the errors'), 'error') data = dict(template='account/register.html', title=gettext("Register"), form=form) return handle_content_type(data)
def del_category(id): """Delete a category.""" try: category = project_repo.get_category(id) if category: if len(cached_cat.get_all()) > 1: ensure_authorized_to('delete', category) if request.method == 'GET': response = dict(template='admin/del_category.html', title=gettext('Delete Category'), category=category, form=dict(csrf=generate_csrf())) return handle_content_type(response) if request.method == 'POST': project_repo.delete_category(category) msg = gettext("Category deleted") flash(msg, 'success') cached_cat.reset() return redirect_content_type(url_for(".categories")) else: msg = gettext('Sorry, it is not possible to delete the only' ' available category. You can modify it, ' ' click the edit button') flash(msg, 'warning') return redirect_content_type(url_for('.categories')) else: abort(404) except HTTPException: raise except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def _show_public_profile(user, form): user_dict = cached_users.public_get_user_summary(user.name) projects_contributed = cached_users.public_projects_contributed_cached(user.id) projects_created = cached_users.public_published_projects_cached(user.id) can_update = False if (user.restrict is False and current_user.is_authenticated() and current_user.admin): draft_projects = cached_users.draft_projects(user.id) projects_created.extend(draft_projects) can_update = True if user.restrict is False: title = "%s · User Profile" % user_dict['fullname'] else: title = "User data is restricted" projects_contributed = [] projects_created = [] form = None response = dict(template='/account/public_profile.html', title=title, user=user_dict, projects=projects_contributed, projects_created=projects_created, form=form, can_update=can_update, input_form=False) return handle_content_type(response)
def tos(): """Render help/terms-of-use page.""" cleaned_up_content = Document(render_template('help/tos.html')).summary() response = dict(template='help/tos.html', content=cleaned_up_content, title='Help: Terms of Use') return handle_content_type(response)
def cookies_policy(): """Render help/cookies-policy page.""" cleaned_up_content = Document(render_template('help/cookies_policy.html')).summary() response = dict(template='help/cookies_policy.html', content=cleaned_up_content, title='Help: Cookies Policy') return handle_content_type(response)
def forgot_password(): """ Request a forgotten password for a user. Returns a Jinja2 template. """ form = ForgotPasswordForm(request.body) if form.validate_on_submit(): user = user_repo.get_by(email_addr=form.email_addr.data) if user and user.email_addr: msg = dict(subject='Account Recovery', recipients=[user.email_addr]) if user.twitter_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Twitter') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Twitter') elif user.facebook_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Facebook') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Facebook') elif user.google_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Google') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Google') else: userdict = {'user': user.name, 'password': user.passwd_hash} key = signer.dumps(userdict, salt='password-reset') recovery_url = url_for_app_type('.reset_password', key=key, _external=True) msg['body'] = render_template( '/account/email/forgot_password.md', user=user, recovery_url=recovery_url) msg['html'] = render_template( '/account/email/forgot_password.html', user=user, recovery_url=recovery_url) mail_queue.enqueue(send_mail, msg) flash(gettext("We've sent you an email with account " "recovery instructions!"), 'success') else: flash(gettext("We don't have this email in our records. " "You may have signed up with a different " "email or used Twitter, Facebook, or " "Google to sign-in"), 'error') if request.method == 'POST' and not form.validate(): flash(gettext('Something went wrong, please correct the errors on the ' 'form'), 'error') data = dict(template='/account/password_forgot.html', form=form) return handle_content_type(data)
def newsletter_subscribe(): """ Register method for subscribing user to PYBOSSA newsletter. Returns a Jinja2 template """ # Save that we've prompted the user to sign up in the newsletter if newsletter.is_initialized() and current_user.is_authenticated(): next_url = request.args.get('next') or url_for('home.home') user = user_repo.get(current_user.id) if current_user.newsletter_prompted is False: user.newsletter_prompted = True user_repo.update(user) if request.args.get('subscribe') == 'True': newsletter.subscribe_user(user) flash("You are subscribed to our newsletter!", 'success') return redirect_content_type(next_url) elif request.args.get('subscribe') == 'False': return redirect_content_type(next_url) else: response = dict(template='account/newsletter.html', title=gettext("Subscribe to our Newsletter"), next=next_url) return handle_content_type(response) else: return abort(404)
def reset_password(): """ Reset password method. Returns a Jinja2 template. """ key = request.args.get('key') if key is None: abort(403) userdict = {} try: timeout = current_app.config.get('ACCOUNT_LINK_EXPIRATION', 3600) userdict = signer.loads(key, max_age=timeout, salt='password-reset') except BadData: abort(403) username = userdict.get('user') if not username or not userdict.get('password'): abort(403) user = user_repo.get_by_name(username) if user.passwd_hash != userdict.get('password'): abort(403) form = ChangePasswordForm(request.body) if form.validate_on_submit(): user.set_password(form.new_password.data) user_repo.update(user) flash(gettext('You reset your password successfully!'), 'success') return _sign_in_user(user) if request.method == 'POST' and not form.validate(): flash(gettext('Please correct the errors'), 'error') response = dict(template='/account/password_reset.html', form=form) return handle_content_type(response)
def result(): """Render a results page.""" try: response = dict(template="/home/_results.html") return handle_content_type(response) except TemplateNotFound: return abort(404)
def index(window=0): """Get the last activity from users and projects.""" if current_user.is_authenticated(): user_id = current_user.id else: user_id = None if window >= 10: window = 10 info = request.args.get('info') leaderboards = current_app.config.get('LEADERBOARDS') if info is not None: if leaderboards is None or info not in leaderboards: return abort(404) top_users = cached_users.get_leaderboard(current_app.config['LEADERBOARD'], user_id=user_id, window=window, info=info) response = dict(template='/stats/index.html', title="Community Leaderboard", top_users=top_users) return handle_content_type(response)
def announcement(): """Manage anncounements.""" announcements = announcement_repo.get_all_announcements() response = dict(template='admin/announcement.html', title=gettext("Manage global Announcements"), announcements=announcements, csrf=generate_csrf()) return handle_content_type(response)
def privacy(): """Render help/privacy policy page.""" # use readability to remove styling and headers cleaned_up_content = Document(render_template('help/privacy.html')).summary() response = dict(template='help/privacy.html', content=cleaned_up_content, title='Privacy Policy') return handle_content_type(response)
def dashboard(): """Show PYBOSSA Dashboard.""" try: if request.args.get('refresh') == '1': db_jobs = get_dashboard_jobs() for j in db_jobs: DASHBOARD_QUEUE.enqueue(j['name']) msg = gettext('Dashboard jobs enqueued,' ' refresh page in a few minutes') flash(msg) active_users_last_week = dashb.format_users_week() active_anon_last_week = dashb.format_anon_week() draft_projects_last_week = dashb.format_draft_projects() published_projects_last_week = dashb.format_published_projects() update_projects_last_week = dashb.format_update_projects() new_tasks_week = dashb.format_new_tasks() new_task_runs_week = dashb.format_new_task_runs() new_users_week = dashb.format_new_users() returning_users_week = dashb.format_returning_users() update_feed = get_update_feed() response = dict( template='admin/dashboard.html', title=gettext('Dashboard'), active_users_last_week=active_users_last_week, active_anon_last_week=active_anon_last_week, draft_projects_last_week=draft_projects_last_week, published_projects_last_week=published_projects_last_week, update_projects_last_week=update_projects_last_week, new_tasks_week=new_tasks_week, new_task_runs_week=new_task_runs_week, new_users_week=new_users_week, returning_users_week=returning_users_week, update_feed=update_feed, wait=False) return handle_content_type(response) except ProgrammingError as e: response = dict(template='admin/dashboard.html', title=gettext('Dashboard'), wait=True) return handle_content_type(response) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def index(): """Return Global Statistics for the site.""" title = "Global Statistics" n_auth = site_stats.n_auth_users() n_anon = site_stats.n_anon_users() n_total_users = n_anon + n_auth n_published_projects = cached_projects.n_published() n_draft_projects = cached_projects.n_count('draft') n_total_projects = n_published_projects + n_draft_projects n_tasks = site_stats.n_tasks_site() n_task_runs = site_stats.n_task_runs_site() top5_projects_24_hours = site_stats.get_top5_projects_24_hours() top5_users_24_hours = site_stats.get_top5_users_24_hours() stats = dict(n_total_users=n_total_users, n_auth=n_auth, n_anon=n_anon, n_published_projects=n_published_projects, n_draft_projects=n_draft_projects, n_total_projects=n_total_projects, n_tasks=n_tasks, n_task_runs=n_task_runs) users = dict(label="User Statistics", values=[ dict(label='Anonymous', value=[0, n_anon]), dict(label='Authenticated', value=[0, n_auth])]) projects = dict(label="Projects Statistics", values=[ dict(label='Published', value=[0, n_published_projects]), dict(label='Draft', value=[0, n_draft_projects])]) tasks = dict(label="Task and Task Run Statistics", values=[ dict(label='Tasks', value=[0, n_tasks]), dict(label='Answers', value=[1, n_task_runs])]) response = dict(template='/stats/global.html', title=title, users=json.dumps(users), projects=json.dumps(projects), tasks=json.dumps(tasks), show_locs=False, top5_users_24_hours=top5_users_24_hours, top5_projects_24_hours=top5_projects_24_hours, stats=stats) return handle_content_type(response)
def update_category(id): """Update a category.""" try: category = project_repo.get_category(id) if category: ensure_authorized_to('update', category) form = CategoryForm(obj=category) form.populate_obj(category) if request.method == 'GET': response = dict(template='admin/update_category.html', title=gettext('Update Category'), category=category, form=form) return handle_content_type(response) if request.method == 'POST': form = CategoryForm(request.body) if form.validate(): slug = form.name.data.lower().replace(" ", "") new_category = Category(id=form.id.data, name=form.name.data, short_name=slug) project_repo.update_category(new_category) cached_cat.reset() msg = gettext("Category updated") flash(msg, 'success') return redirect_content_type(url_for(".categories")) else: msg = gettext("Please correct the errors") flash(msg, 'success') response = dict(template='admin/update_category.html', title=gettext('Update Category'), category=category, form=form) return handle_content_type(response) else: abort(404) except HTTPException: raise except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def test_handle_content_type_json(self, mocklast, mockjsonify, mockrender, mockrequest): fake_d = {'Content-Type': 'application/json'} mockrequest.headers.__getitem__.side_effect = fake_d.__getitem__ mockrequest.headers.get.side_effect = fake_d.get mockrequest.headers.__iter__.side_effect = fake_d.__iter__ mockjsonify.side_effect = myjsonify res = util.handle_content_type(dict(template='example.html')) err_msg = "template key should exist" assert res.get('template') == 'example.html', err_msg err_msg = "jsonify should be called" assert mockjsonify.called, err_msg
def api(): """Render help/api page.""" categories = cached_cat.get_used() projects = cached_projects.get(categories[0]['short_name']) if len(projects) > 0: project_id = choice(projects)['id'] else: # pragma: no cover project_id = None response = dict(template='help/api.html', title="Help: API", project_id=project_id) return handle_content_type(response)
def home(): """Render home page with the cached projects and users.""" page = 1 per_page = current_app.config.get('APPS_PER_PAGE', 5) # Add featured tmp_projects = cached_projects.get_featured('featured', page, per_page) if len(tmp_projects) > 0: data = dict(featured=rank(tmp_projects)) else: data = dict(featured=[]) response = dict(template='/home/index.html', **data) return handle_content_type(response)
def users(user_id=None): """Manage users of PYBOSSA.""" form = SearchForm(request.body) users = [user for user in user_repo.filter_by(admin=True) if user.id != current_user.id] if request.method == 'POST' and form.user.data: query = form.user.data found = [user for user in user_repo.search_by_name(query) if user.id != current_user.id] [ensure_authorized_to('update', found_user) for found_user in found] if not found: markup = Markup('<strong>{}</strong> {} <strong>{}</strong>') flash(markup.format(gettext("Ooops!"), gettext("We didn't find a user matching your query:"), form.user.data)) response = dict(template='/admin/users.html', found=found, users=users, title=gettext("Manage Admin Users"), form=form) return handle_content_type(response) response = dict(template='/admin/users.html', found=[], users=users, title=gettext("Manage Admin Users"), form=form) return handle_content_type(response)
def test_handle_content_type_json_pagination(self, mocklast, mockjsonify, mockrender, mockrequest): fake_d = {'Content-Type': 'application/json'} mockrequest.headers.__getitem__.side_effect = fake_d.__getitem__ mockrequest.headers.get.side_effect = fake_d.get mockrequest.headers.__iter__.side_effect = fake_d.__iter__ mockjsonify.side_effect = myjsonify pagination = util.Pagination(page=1, per_page=5, total_count=10) res = util.handle_content_type(dict(template='example.html', pagination=pagination)) err_msg = "template key should exist" assert res.get('template') == 'example.html', err_msg err_msg = "jsonify should be called" assert mockjsonify.called, err_msg err_msg = "Pagination should exist" assert res.get('pagination') is not None, err_msg assert res.get('pagination') == pagination.to_json(), err_msg
def _show_public_profile(user): user_dict = cached_users.public_get_user_summary(user.name) projects_contributed = cached_users.public_projects_contributed_cached(user.id) projects_created = cached_users.public_published_projects_cached(user.id) if current_user.is_authenticated() and current_user.admin: draft_projects = cached_users.draft_projects(user.id) projects_created.extend(draft_projects) title = "%s · User Profile" % user_dict['fullname'] response = dict(template='/account/public_profile.html', title=title, user=user_dict, projects=projects_contributed, projects_created=projects_created) return handle_content_type(response)
def _show_own_profile(user): user_dict = cached_users.get_user_summary(user.name) rank_and_score = cached_users.rank_and_score(user.id) user.rank = rank_and_score['rank'] user.score = rank_and_score['score'] user.total = cached_users.get_total_users() projects_contributed = cached_users.public_projects_contributed_cached(user.id) projects_published, projects_draft = _get_user_projects(user.id) cached_users.get_user_summary(user.name) response = dict(template='account/profile.html', title=gettext("Profile"), projects_contrib=projects_contributed, projects_published=projects_published, projects_draft=projects_draft, user=user_dict) return handle_content_type(response)
def featured(project_id=None): """List featured projects of PYBOSSA.""" try: if request.method == 'GET': categories = cached_cat.get_all() projects = {} for c in categories: n_projects = cached_projects.n_count(category=c.short_name) projects[c.short_name] = cached_projects.get( category=c.short_name, page=1, per_page=n_projects) response = dict(template = '/admin/projects.html', projects=projects, categories=categories, form=dict(csrf=generate_csrf())) return handle_content_type(response) else: project = project_repo.get(project_id) if project: ensure_authorized_to('update', project) if request.method == 'POST': if project.featured is True: msg = "Project.id %s already featured" % project_id return format_error(msg, 415) cached_projects.reset() project.featured = True project_repo.update(project) return json.dumps(project.dictize()) if request.method == 'DELETE': if project.featured is False: msg = 'Project.id %s is not featured' % project_id return format_error(msg, 415) cached_projects.reset() project.featured = False project_repo.update(project) return json.dumps(project.dictize()) else: msg = 'Project.id %s not found' % project_id return format_error(msg, 404) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def test_handle_content_type_html(self, mockjsonify, mockrender, mockrequest): fake_d = {'Content-Type': 'text/html'} mockrequest.headers.__getitem__.side_effect = fake_d.__getitem__ mockrequest.headers.get.side_effect = fake_d.get mockrequest.headers.__iter__.side_effect = fake_d.__iter__ mockjsonify.side_effect = myjsonify mockrender.side_effect = myrender pagination = util.Pagination(page=1, per_page=5, total_count=10) template, data = util.handle_content_type(dict(template='example.html', pagination=pagination)) err_msg = "Template should be rendered" assert template == 'example.html', err_msg err_msg = "Template key should not exist" assert data.get('template') is None, err_msg err_msg = "jsonify should not be called" assert mockjsonify.called is False, err_msg err_msg = "render_template should be called" assert mockrender.called is True, err_msg
def home(): """Render home page with the cached projects and users.""" page = 1 per_page = current_app.config.get('APPS_PER_PAGE', 5) # Add featured tmp_projects = cached_projects.get_featured('featured', page, per_page) if len(tmp_projects) > 0: data = dict(featured=rank(tmp_projects)) else: data = dict(featured=[]) # Add historical contributions historical_projects = [] if current_user.is_authenticated: user_id = current_user.id historical_projects = cached_users.projects_contributed(user_id, order_by='last_contribution')[:3] data['historical_contributions'] = historical_projects response = dict(template='/home/index.html', **data) return handle_content_type(response)
def delete(name): """ Delete user account. """ user = user_repo.get_by_name(name) if not user: return abort(404) if current_user.name != name: return abort(403) super_queue.enqueue(delete_account, user.id) if (request.headers.get('Content-Type') == 'application/json' or request.args.get('response_format') == 'json'): response = dict(job='enqueued', template='account/delete.html') return handle_content_type(response) else: return redirect(url_for('account.signout'))
def test_handle_content_type_json_error(self, mocklast, mockjsonify, mockrender, mockrequest): fake_d = {'Content-Type': 'application/json'} mockrequest.headers.__getitem__.side_effect = fake_d.__getitem__ mockrequest.headers.get.side_effect = fake_d.get mockrequest.headers.__iter__.side_effect = fake_d.__iter__ mockjsonify.side_effect = myjsonify res, code = util.handle_content_type( dict( template='example.html', code=404, description="Not found")) err_msg = "template key should exist" assert res.get('template') == 'example.html', err_msg err_msg = "jsonify should be called" assert mockjsonify.called, err_msg err_msg = "Error code should exist" assert res.get('code') == 404, err_msg assert code == 404, err_msg err_msg = "Error description should exist" assert res.get('description') is not None, err_msg
def projects(name): """ List user's project list. Returns a Jinja2 template with the list of projects of the user. """ user = user_repo.get_by_name(name) if not user: return abort(404) if current_user.name != name: return abort(403) user = user_repo.get(current_user.id) projects_published, projects_draft = _get_user_projects(user.id) response = dict(template='account/projects.html', title=gettext("Projects"), projects_published=projects_published, projects_draft=projects_draft) return handle_content_type(response)
def index(page=1): """Index page for all PYBOSSA registered users.""" update_feed = get_update_feed() per_page = 24 count = cached_users.get_total_users() accounts = cached_users.get_users_page(page, per_page) if not accounts and page != 1: abort(404) pagination = Pagination(page, per_page, count) if current_user.is_authenticated(): user_id = current_user.id else: user_id = None top_users = cached_users.get_leaderboard(current_app.config['LEADERBOARD'], user_id) tmp = dict(template='account/index.html', accounts=accounts, total=count, top_users=top_users, title="Community", pagination=pagination, update_feed=update_feed) return handle_content_type(tmp)
def test_handle_content_type_json_form(self, mocklast, mockcsrf, mockjsonify, mockrender, mockrequest): fake_d = {'Content-Type': 'application/json'} mockrequest.headers.__getitem__.side_effect = fake_d.__getitem__ mockrequest.headers.get.side_effect = fake_d.get mockrequest.headers.__iter__.side_effect = fake_d.__iter__ mockjsonify.side_effect = myjsonify mockcsrf.return_value = "yourcsrf" form = MagicMock(spec=Form, data=dict(foo=1), errors=None) res = util.handle_content_type(dict(template='example.html', form=form)) err_msg = "template key should exist" assert res.get('template') == 'example.html', err_msg err_msg = "jsonify should be called" assert mockjsonify.called, err_msg err_msg = "Form should exist" assert res.get('form'), err_msg err_msg = "Form should have a csrf key/value" assert res.get('form').get('csrf') == 'yourcsrf', err_msg err_msg = "There should be the keys of the form" keys = ['foo', 'errors', 'csrf'] assert res.get('form').keys().sort() == keys.sort(), err_msg
def respond(): response = dict(template='admin/new_announcement.html', title=gettext("Edit a post"), levelOptions=json.dumps(current_app.config['ANNOUNCEMENT_LEVEL_OPTIONS']), form=form) return handle_content_type(response)
def respond(): response = dict(template='admin/new_announcement.html', title=gettext("Edit a post"), form=form) return handle_content_type(response)
def index(): """Return Global Statistics for the site.""" title = "Global Statistics" n_auth = site_stats.n_auth_users() n_anon = site_stats.n_anon_users() n_total_users = n_anon + n_auth n_published_projects = cached_projects.n_published() n_draft_projects = cached_projects.n_count('draft') n_total_projects = n_published_projects + n_draft_projects n_tasks = site_stats.n_tasks_site() n_task_runs = site_stats.n_task_runs_site() top5_projects_24_hours = site_stats.get_top5_projects_24_hours() top5_users_24_hours = site_stats.get_top5_users_24_hours() locs = site_stats.get_locs() show_locs = False if len(locs) > 0: show_locs = True stats = dict(n_total_users=n_total_users, n_auth=n_auth, n_anon=n_anon, n_published_projects=n_published_projects, n_draft_projects=n_draft_projects, n_total_projects=n_total_projects, n_tasks=n_tasks, n_task_runs=n_task_runs) users = dict(label="User Statistics", values=[ dict(label='Anonymous', value=[0, n_anon]), dict(label='Authenticated', value=[0, n_auth]) ]) projects = dict(label="Projects Statistics", values=[ dict(label='Published', value=[0, n_published_projects]), dict(label='Draft', value=[0, n_draft_projects]) ]) tasks = dict(label="Task and Task Run Statistics", values=[ dict(label='Tasks', value=[0, n_tasks]), dict(label='Answers', value=[1, n_task_runs]) ]) response = dict(template='/stats/global.html', title=title, users=json.dumps(users), projects=json.dumps(projects), tasks=json.dumps(tasks), locs=json.dumps(locs), show_locs=show_locs, top5_users_24_hours=top5_users_24_hours, top5_projects_24_hours=top5_projects_24_hours, stats=stats) return handle_content_type(response)
def _bad_request(e): response = dict(template='400.html', code=400, description=BADREQUEST) return handle_content_type(response)
def index(): """List admin actions.""" key = NOTIFY_ADMIN + str(current_user.id) sentinel.master.delete(key) return handle_content_type(dict(template='/admin/index.html'))
def csrf_error_handler(reason): response = dict(template='400.html', code=400, description=reason) return handle_content_type(response)
def search(): """Render search results page.""" response = dict(template="/home/search.html") return handle_content_type(response)
def register(): """ Register method for creating a PYBOSSA account. Returns a Jinja2 template """ if current_app.config.get('LDAP_HOST', False): return abort(404) if not app_settings.upref_mdata: form = RegisterForm(request.body) else: form = RegisterFormWithUserPrefMetadata(request.body) form.set_upref_mdata_choices() form.project_slug.choices = get_project_choices() msg = "I accept receiving emails from %s" % current_app.config.get('BRAND') form.consent.label = msg if request.method == 'POST': form.generate_password() if request.method == 'POST' and form.validate(): if app_settings.upref_mdata: user_pref, metadata = get_user_pref_and_metadata( form.name.data, form) account = dict(fullname=form.fullname.data, name=form.name.data, email_addr=form.email_addr.data, password=form.password.data, consent=form.consent.data, user_type=form.user_type.data) account['user_pref'] = user_pref account['metadata'] = metadata else: account = dict(fullname=form.fullname.data, name=form.name.data, email_addr=form.email_addr.data, password=form.password.data, consent=form.consent.data) ensure_data_access_assignment_from_form(account, form) confirm_url = get_email_confirmation_url(account) if current_app.config.get('ACCOUNT_CONFIRMATION_DISABLED'): project_slugs = form.project_slug.data create_account(account, project_slugs=project_slugs) flash(gettext('Created user succesfully!'), 'success') return redirect_content_type(url_for("home.home")) msg = dict(subject='Welcome to %s!' % current_app.config.get('BRAND'), recipients=[account['email_addr']], body=render_template('/account/email/validate_account.md', user=account, confirm_url=confirm_url)) msg['html'] = markdown(msg['body']) mail_queue.enqueue(send_mail, msg) data = dict(template='account/account_validation.html', title=gettext("Account validation"), status='sent') return handle_content_type(data) if request.method == 'POST' and not form.validate(): flash(gettext('Please correct the errors'), 'error') del form.password del form.confirm data = dict(template='account/register.html', title=gettext("Register"), form=form) return handle_content_type(data)
def signin(): """ Signin method for PYBOSSA users. Returns a Jinja2 template with the result of signing process. """ form = LoginForm(request.body) isLdap = current_app.config.get('LDAP_HOST', False) if (request.method == 'POST' and form.validate() and isLdap is False): password = form.password.data email_addr = form.email.data.lower() user = user_repo.search_by_email(email_addr=email_addr) if user and user.check_password(password): if not current_app.config.get('ENABLE_TWO_FACTOR_AUTH'): msg_1 = gettext('Welcome back') + ' ' + user.fullname flash(msg_1, 'success') return _sign_in_user(user) else: _email_two_factor_auth(user) url_token = otp.generate_url_token(user.email_addr) next_url = is_own_url_or_else(request.args.get('next'), url_for('home.home')) return redirect_content_type( url_for('account.otpvalidation', token=url_token, next=next_url)) elif user: msg, method = get_user_signup_method(user) if method == 'local': msg = gettext('Ooops, Incorrect email/password') flash(msg, 'error') else: flash(msg, 'info') else: msg = gettext("Ooops, we didn't find you in the system, \ did you sign up?") flash(msg, 'info') if (request.method == 'POST' and form.validate() and isLdap): password = form.password.data cn = form.email.data ldap_user = None if ldap.bind_user(cn, password): ldap_user = ldap.get_object_details(cn) key = current_app.config.get('LDAP_USER_FILTER_FIELD') value = ldap_user[key][0] user_db = user_repo.get_by(ldap=value) if (user_db is None): keyfields = current_app.config.get('LDAP_PYBOSSA_FIELDS') user_data = dict( fullname=ldap_user[keyfields['fullname']][0], name=ldap_user[keyfields['name']][0], email_addr=ldap_user[keyfields['email_addr']][0], valid_email=True, ldap=value, consent=True) create_account(user_data, ldap_disabled=False) else: login_user(user_db, remember=True) else: msg = gettext("User LDAP credentials are wrong.") flash(msg, 'info') if request.method == 'POST' and not form.validate(): flash(gettext('Please correct the errors'), 'error') auth = {'twitter': False, 'facebook': False, 'google': False} if current_user.is_anonymous: # If Twitter is enabled in config, show the Twitter Sign in button if (isLdap is False): if ('twitter' in current_app.blueprints): # pragma: no cover auth['twitter'] = True if ('facebook' in current_app.blueprints): # pragma: no cover auth['facebook'] = True if ('google' in current_app.blueprints): # pragma: no cover auth['google'] = True next_url = is_own_url_or_else(request.args.get('next'), url_for('home.home')) response = dict(template='account/signin.html', title="Sign in", form=form, auth=auth, next=next_url) return handle_content_type(response) else: # User already signed in, so redirect to home page return redirect_content_type(url_for("home.home"))
def handle_csrf_error(e): response = dict(template='400.html', code=400, description=CSRFERROR) return handle_content_type(response)
def _page_not_found(e): response = dict(template='404.html', code=404, description=NOTFOUND) return handle_content_type(response)
def update_profile(name): """ Update user's profile. Returns Jinja2 template. """ user = user_repo.get_by_name(name) if not user: return abort(404) if current_user.name != name: return abort(403) ensure_authorized_to('update', user) show_passwd_form = True if user.twitter_user_id or user.google_user_id or user.facebook_user_id: show_passwd_form = False usr = cached_users.get_user_summary(name, current_user) # Extend the values user.rank = usr.get('rank') user.score = usr.get('score') btn = request.body.get('btn', 'None').capitalize() if btn != 'Profile': update_form = UpdateProfileForm(formdata=None, obj=user) else: update_form = UpdateProfileForm(obj=user) update_form.set_locales(current_app.config['LOCALES']) avatar_form = AvatarUploadForm() password_form = ChangePasswordForm() title_msg = "Update your profile: %s" % user.fullname if request.method == 'POST': # Update user avatar succeed = False btn = request.body.get('btn', 'None').capitalize() if btn == 'Upload': succeed = _handle_avatar_update(user, avatar_form) # Update user profile elif btn == 'Profile': succeed = _handle_profile_update(user, update_form) # Update user password elif btn == 'Password': succeed = _handle_password_update(user, password_form) # Update user external services elif btn == 'External': succeed = _handle_external_services_update(user, update_form) # Otherwise return 415 else: return abort(415) if succeed: cached_users.delete_user_summary(user.name) return redirect_content_type(url_for('.update_profile', name=user.name), status=SUCCESS) else: data = dict(template='/account/update.html', form=update_form, upload_form=avatar_form, password_form=password_form, title=title_msg, show_passwd_form=show_passwd_form) return handle_content_type(data) data = dict(template='/account/update.html', form=update_form, upload_form=avatar_form, password_form=password_form, title=title_msg, show_passwd_form=show_passwd_form) return handle_content_type(data)
def forgot_password(): """ Request a forgotten password for a user. Returns a Jinja2 template. """ form = ForgotPasswordForm(request.body) data = dict(template='/account/password_forgot.html', form=form) if form.validate_on_submit(): email_addr = form.email_addr.data.lower() user = user_repo.get_by(email_addr=email_addr) if user and not user.enabled: brand = current_app.config['BRAND'] flash( gettext('Your account is disabled. ' 'Please contact your {} administrator.'.format(brand)), 'error') return handle_content_type(data) if user and user.email_addr: msg = dict(subject='Account Recovery', recipients=[user.email_addr]) if user.twitter_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Twitter') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Twitter') elif user.facebook_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Facebook') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Facebook') elif user.google_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Google') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Google') else: userdict = {'user': user.name, 'password': user.passwd_hash} key = signer.dumps(userdict, salt='password-reset') recovery_url = url_for_app_type('.reset_password', key=key, _external=True) msg['body'] = render_template( '/account/email/forgot_password.md', user=user, recovery_url=recovery_url, key=key) msg['html'] = render_template( '/account/email/forgot_password.html', user=user, recovery_url=recovery_url, key=key) mail_queue.enqueue(send_mail, msg) flash( gettext("We've sent you an email with account " "recovery instructions!"), 'success') else: flash( gettext("We don't have this email in our records. " "You may have signed up with a different " "email"), 'error') if request.method == 'POST': if not form.validate(): flash( gettext( 'Something went wrong, please correct the errors on the ' 'form'), 'error') else: return redirect_content_type(url_for('account.password_reset_key')) return handle_content_type(data)
def _unauthorized(e): response = dict(template='401.html', code=401, description=UNAUTHORIZED) return handle_content_type(response)
def about(): """Render the about template.""" response = dict(template="/home/about.html") return handle_content_type(response)
def forgot_password(): """ Request a forgotten password for a user. Returns a Jinja2 template. """ form = ForgotPasswordForm(request.body) if form.validate_on_submit(): user = user_repo.get_by(email_addr=form.email_addr.data) if user and user.email_addr: msg = dict(subject='Account Recovery', recipients=[user.email_addr]) if user.twitter_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Twitter') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Twitter') elif user.facebook_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Facebook') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Facebook') elif user.google_user_id: msg['body'] = render_template( '/account/email/forgot_password_openid.md', user=user, account_name='Google') msg['html'] = render_template( '/account/email/forgot_password_openid.html', user=user, account_name='Google') else: userdict = {'user': user.name, 'password': user.passwd_hash} key = signer.dumps(userdict, salt='password-reset') recovery_url = url_for_app_type('.reset_password', key=key, _external=True) msg['body'] = render_template( '/account/email/forgot_password.md', user=user, recovery_url=recovery_url) msg['html'] = render_template( '/account/email/forgot_password.html', user=user, recovery_url=recovery_url) mail_queue.enqueue(send_mail, msg) flash( gettext("We've sent you an email with account " "recovery instructions!"), 'success') else: flash( gettext("We don't have this email in our records. " "You may have signed up with a different " "email or used Twitter, Facebook, or " "Google to sign-in"), 'error') if request.method == 'POST' and not form.validate(): flash( gettext('Something went wrong, please correct the errors on the ' 'form'), 'error') data = dict(template='/account/password_forgot.html', form=form) return handle_content_type(data)
def index(): """Render the default help page.""" response = dict(template='help/index.html', title='Help') return handle_content_type(response)
def license(): """Render help/license page.""" response = dict(template='help/license.html', title='Help: Licenses') return handle_content_type(response)
def _forbidden(e): response = dict(template='403.html', code=403, description=FORBIDDEN) return handle_content_type(response)
def _server_error(e): # pragma: no cover response = dict(template='500.html', code=500, description=INTERNALSERVERERROR) return handle_content_type(response)