def help_latest(location=None, category=None): """automatically selects next inquiry""" if not category or category == 'all': inquiry = Inquiry.latest(location=location) else: inquiry = Inquiry.latest(location=location, category=category) delayed_id, delayed = request.args.get('delayed_id', None), None if not inquiry: return redirect(url_for('admin.home', notification=NOTIF_HELP_DONE)) if g.queue.setting('inquiry_types').enabled and not category and g.queue.setting('inquiry_type_selection').enabled: categories = [(cat, Inquiry.query.filter_by( category=cat, status='unresolved', location=location, queue_id=g.queue.id).count()) for cat in g.queue.setting('inquiry_types').value.split(',')] categories = [c for c in categories if c[1]] if len(categories) > 1: return render_admin('categories.html', title='Request Type', location=location, categories=categories) if delayed_id: delayed = Inquiry.query.get(delayed_id) delayed.unlock() inquiry.lock() inquiry.link(current_user()) return redirect(url_for('admin.help_inquiry', id=inquiry.id, location=location))
def get_home(user, **kwargs): """Return home URL for given user""" if getattr(g, 'queue', None): if user and user.can('admin'): return url_for('admin.home', **kwargs) return url_for('queue.home', **kwargs) return url_for('dashboard.home')
def login(home=None, login=None): """ Login using Google authentication :param str home: URL for queue homepage :param str login: URL for queue login page """ try: flow = client.flow_from_clientsecrets( 'client_secrets.json', scope='openid profile email', redirect_uri=login or url_for('public.login', _external=True)) if 'code' not in request.args: auth_uri = flow.step1_get_authorize_url() return redirect(auth_uri+'&prompt=select_account') credentials = flow.step2_exchange(request.args.get('code')) session['credentials'] = credentials.to_json() http = credentials.authorize(httplib2.Http()) person = service.people().get(userId='me').execute(http=http) user = User.query.filter_by(google_id=person['id']).first() if not user: user = User( name=person['displayName'], email=person['emails'][0]['value'], google_id=person['id'], image_url=person['image']['url'] ).save() else: user.update(image_url=person['image']['url']).save() flask_login.login_user(user) return redirect(home or url_for('public.home')) except client.FlowExchangeError: return redirect(login or url_for('public.login'))
def help_inquiry(id: str, location: str=None) -> str: """automatically selects next inquiry or reloads inquiry.""" inquiry = Inquiry.query.get(id).maybe_lock() if request.method == 'POST': delayed_id = None inquiry.resolution.close() emitQueuePositions(inquiry) emitQueueInfo(inquiry.queue) if request.form['status'] == 'resolved': inquiry.resolved() elif request.form['status'] == 'unresolved': delayed_id = id if request.form['load_next'] != 'y': if request.form['status'] == 'unresolved': inquiry.unlock() return redirect(url_for('admin.home')) return redirect( url_for( 'admin.help_latest', location=location, delayed_id=delayed_id)) return render_admin( 'help_inquiry.html', inquiry=inquiry, inquiries=Inquiry.get_current_user_inquiries(), hide_event_nav=True, group=inquiry.get_similar_inquiries(), wait_time=inquiry.get_wait_time('%h:%m:%s'))
def promote(role_name: str=None) -> str: """Promote the user accessing this page.""" if not current_user().is_authenticated: abort(401, 'You need to be logged in to promote an account!') part = Participant.get_from_user(current_user()) if part and part.role.name == 'Owner' and g.queue.get_num_owners() <= 1: abort(401, 'You cannot demote yourself from owner until another owner' ' has been added.') if not role_name: return render_queue( 'roles.html', title='Promotion Form', message='Welcome. Please select a role below.', roles=g.queue.get_roles_for_promotion()) form = PromotionForm(request.form) if request.method == 'POST' or g.queue.get_code_for_role(role_name) == '*': if not g.queue.is_promotion_valid(role_name, request.form['code']): form.errors.setdefault('code', []).append('Incorrect code.') return render_queue( 'form.html', form=form, submit='Promote', back=url_for('queue.promote')) Participant.update_or_create(current_user(), role_name) return render_queue( 'confirm.html', title='Promotion Success', message='You have been promoted to %s' % role_name, action='Onward', url=url_for('admin.home')) return render_queue( 'form.html', form=form, submit='Promote', back=url_for('queue.promote'))
def logout(home: str = None) -> str: """Log out current session and redirect to home. :param home: URL to redirect to after logout success """ flask_login.logout_user() return redirect(request.args.get("redirect", home or url_for("public.home")))
def requeue(inquiry_id: str) -> str: """Requeue the provided inquiry.""" delayed = Inquiry.query.get(inquiry_id) delayed.unlock() emitQueuePositions(delayed) emitQueueInfo(delayed.queue) return redirect(url_for('admin.resolved'))
def settings(): """settings""" settings = sorted(QueueSetting.query.join(Queue).filter_by( id=g.queue.id).all(), key=lambda s: s.name) if g.participant.role.name.lower() != 'owner': settings = [s for s in settings if s.name != 'whitelist'] for setting in settings: if setting.name in default_queue_settings: # NOTE: this will filter out settings not in the default settings list default_description = default_queue_settings[setting.name]['description'] if default_description != setting.description: setting.description = default_description if request.method == 'POST': notification = NOTIF_SETTING_UPDATED setting = QueueSetting.query.filter_by( queue_id=g.queue.id, name=request.form['name']).first() for k, v in request.form.items(): setattr(setting, k, v) if setting.name == 'locations': setting.value = setting.value.replace(' ','') setting.save() return redirect(url_for('admin.settings', notification=notification)) return render_admin('settings.html', settings=settings)
def home() -> str: """List all unresolved inquiries for the homepage.""" if current_user().can('help'): return redirect(url_for('admin.home')) return render_queue( 'landing.html', num_inquiries=Inquiry.get_num_unresolved(), ttr=g.queue.ttr())
def home(): """list all unresolved inquiries for the homepage""" if current_user().can('help'): return redirect(url_for('admin.home')) return render_queue('landing.html', num_inquiries=Inquiry.query.filter_by( status='unresolved', queue_id=g.queue.id).count(), ttr=g.queue.ttr())
def logout(home=None): """ Logs out current session and redirects to home :param str home: URL to redirect to after logout success """ flask_login.logout_user() return redirect(request.args.get('redirect', home or url_for('public.home')))
def inquiry() -> str: """Place a new request. This request which may be authored by either a system user or an anonymous user. """ user = current_user() if not user.is_authenticated and \ g.queue.setting(name='require_login').enabled: return render_queue( 'confirm.html', title='Login Required', message='Login to add an inquiry, and start using this queue.') form = InquiryForm(request.form, obj=user) n = int(g.queue.setting(name='max_requests').value) if User.get_num_current_requests(request.form.get('name', None)) >= n: if not current_user().is_authenticated: message = 'If you haven\'t submitted a request, try' ' logging in and re-requesting.' else: message = 'Would you like to cancel your oldest request?' return render_queue( 'confirm.html', title='Oops', message='Looks like you\'ve reached the maximum number of times ' 'you can add yourself to the queue at once (<code>%d</code>). ' '%s' % (n, message), action='Cancel Oldest Request', url=url_for('queue.cancel')) form.location.choices = choicify(g.queue.setting('locations').value) form.category.choices = choicify(g.queue.setting('inquiry_types').value) if request.method == 'POST' and form.validate() and \ g.queue.is_valid_assignment(request, form): inquiry = Inquiry(**request.form).update(queue_id=g.queue.id) if current_user().is_authenticated: inquiry.owner_id = current_user().id inquiry.save() emitQueueInfo(g.queue) return redirect(url_for('queue.waiting', inquiry_id=inquiry.id)) return render_queue( 'form.html', form=form, title='Request Help', submit='Request Help')
def clear() -> str: """Clear all inquiries, period.""" context = {'action': 'Admin Home', 'url': url_for('admin.home')} if request.method == 'POST': Inquiry.clear_all_inquiries() context['message'] = 'All Cleared' return render_admin('admin_confirm.html', **context) context['message'] = 'Are you sure? This will clear all resolving and' 'unresolved.<form method="POST"><input type="submit" value="clear"></form>' return render_admin('admin_confirm.html', **context)
def cancel(inquiry_id=None): """Cancel placed request""" inquiry = Inquiry.query.get(inquiry_id) if inquiry_id else Inquiry.query.filter_by( owner_id=current_user().id, status='unresolved', queue_id=g.queue.id).first() anon = not current_user().is_authenticated and not inquiry.owner_id non_anon = current_user().is_authenticated and inquiry.owner_id == current_user().id if anon or non_anon: inquiry.update(status='closed').save() else: return render_queue('error.html', code='404', message='You cannot cancel another user\'s request. This incident has been logged.', url=url_for('queue.home'), action='Back Home') emitQueuePositions(inquiry) emitQueueInfo(inquiry.queue) return redirect(url_for('queue.home'))
def inquiry(): """ Place a new request, which may be authored by either a system user or an anonymous user. """ user, form = flask_login.current_user, InquiryForm(request.form) if user.is_authenticated: form = InquiryForm(request.form, obj=user) elif g.queue.setting(name='require_login').enabled: return render_queue('confirm.html', title='Login Required', message='Login to add an inquiry, and start using this queue.') n = int(g.queue.setting(name='max_requests').value) filter_id = User.email == current_user().email if \ current_user().is_authenticated else User.name == request.form.get('name', None) not_logged_in_max = '' if Inquiry.query.join(User).filter( filter_id, Inquiry.status=='unresolved', Inquiry.queue_id==g.queue.id ).count() >= n: if not current_user().is_authenticated: not_logged_in_max = 'If you haven\'t submitted a request, try logging in and re-requesting.' return render_queue('confirm.html', title='Oops', message='Looks like you\'ve reached the maximum number of times you can add yourself to the queue at once (<code>%d</code>). %s' % (n, not_logged_in_max or 'Would you like to cancel your oldest request?'), action='Cancel Oldest Request', url=url_for('queue.cancel')) form.location.choices = choicify( g.queue.setting('locations').value.split(',')) form.category.choices = choicify( g.queue.setting('inquiry_types').value.split(',')) if request.method == 'POST' and form.validate() and \ g.queue.is_valid_assignment(request, form): inquiry = Inquiry(**request.form) inquiry.queue_id = g.queue.id if current_user().is_authenticated: inquiry.owner_id = current_user().id inquiry.save() emitQueueInfo(g.queue) return redirect(url_for('queue.waiting', inquiry_id=inquiry.id)) return render_queue('form.html', form=form, title='Request Help', submit='Request Help')
def cancel(inquiry_id: int=None) -> str: """Cancel placed request.""" inquiry = get_inquiry_for_asker(inquiry_id) if inquiry.is_owned_by_current_user(): inquiry.close() else: abort(401, 'You cannot cancel another user\'s request. This incident' ' has been logged.') emitQueuePositions(inquiry) emitQueueInfo(inquiry.queue) return redirect(url_for('queue.home'))
def clear(location=None): """Clear all inquiries, period. Or, clear all inquiries for a location.""" if location: return 'Not yet implemented.' if request.method == 'POST': Inquiry.query.filter_by( status='unresolved', queue_id=g.queue.id).update({'status': 'closed'}) Inquiry.query.filter_by( status='resolving', queue_id=g.queue.id).update({'status': 'closed'}) db.session.commit() return render_admin('admin_confirm.html', message='All Cleared', action='Admin Home', url=url_for('admin.home')) return render_admin('admin_confirm.html', message='Are you sure? This will clear all resolving and unresolved. \ <form method="POST"><input type="submit" value="clear"></form>', action='admin home', url=url_for('admin.home'))
def help_latest(location: str=None, category: str=None) -> str: """Automatically select next inquiry.""" if g.queue.show_inquiry_types() and not category: categories = Inquiry.get_categories_unresolved(location=location) if len(categories) > 1: return render_admin( 'categories.html', title='Request Type', location=location, categories=categories) inquiry = Inquiry.get_current_or_latest( location=location, category=category) Inquiry.maybe_unlock_delayed() if not inquiry: return redirect(url_for('admin.home', notification=NOTIF_HELP_DONE)) inquiry.lock().link(current_user()) return redirect(url_for( 'admin.help_inquiry', id=inquiry.id, location=location))
def help_inquiry(id, location=None): """automatically selects next inquiry or reloads inquiry """ inquiry = Inquiry.query.get(id) if not inquiry.resolution: inquiry.lock() inquiry.link(current_user()) if request.method == 'POST': delayed_id=None inquiry.resolution.close() # emit new queue positions emitQueuePositions(inquiry) emitQueueInfo(inquiry.queue) if request.form['status'] == 'unresolved': delayed_id = inquiry.id else: inquiry.close() if request.form['load_next'] != 'y': if delayed_id: delayed = Inquiry.query.get(delayed_id) delayed.unlock() return redirect(url_for('admin.home')) if not location: return redirect(url_for('admin.help_latest', delayed_id=delayed_id)) return redirect(url_for('admin.help_latest', location=location, delayed_id=delayed_id)) return render_admin('help_inquiry.html', inquiry=inquiry, inquiries=Inquiry.query.filter_by(name=inquiry.name).limit(10).all(), hide_event_nav=True, group=Inquiry.query.filter( Inquiry.status == 'unresolved', Inquiry.queue_id == g.queue.id, Inquiry.assignment == inquiry.assignment, Inquiry.problem == inquiry.problem, Inquiry.owner_id != inquiry.owner_id ).all(), wait_time=strfdelta( inquiry.resolution.created_at-inquiry.created_at, '%h:%m:%s'))
def create_queue(): """create queue form""" form = QueueForm(request.form) if request.method == 'POST' and form.validate(): queue = Queue.from_request().save().load_roles( default_queue_roles[request.form['category']]).save() current_user().join(queue, role='Owner') queue.load_settings('whitelist') return redirect(url_for('queue.home', queue_url=queue.url)) return render_dashboard('form_public.html', title='Create Queue', submit='create', form=form)
def login(home: str = None, login: str = None) -> str: """Login using Google authentication. :param home: URL for queue homepage :param login: URL for queue login page """ try: flow = get_google_auth_flow(login) if "code" not in request.args: return redirect(get_google_authorize_uri(flow)) person = get_google_person(flow) user = User.query.filter_by(google_id=person["id"]).first() if not user: user = User( name=person["displayName"], email=person["emails"][0]["value"], google_id=person["id"], image_url=person["image"]["url"], ).save() flask_login.login_user(user) return redirect(home or url_for("public.home")) except client.FlowExchangeError: return redirect(login or url_for("public.login"))
def settings() -> str: """Show settings for the current queue.""" if request.method == 'POST': notification = NOTIF_SETTING_UPDATED setting = ( g.queue .setting(request.form['name']) .update(**dict(request.form.items()))) # TODO convert all settings into objects, with permissions check and # post processing if setting.name == 'locations': setting.value = setting.value.replace(' ', '') if setting.name == 'inquiry_types' and \ len(str2lst(setting.value)) == 1 and \ bool(int(setting.enabled)) is True: notification = NOTIF_SETTING_ONE_TYPE setting.save() return redirect(url_for( 'admin.settings', notification=notification)) return render_admin('settings.html', settings=g.queue.cleaned_settings)
def requeue(inquiry_id): delayed = Inquiry.query.get(inquiry_id) delayed.unlock() emitQueuePositions(delayed) emitQueueInfo(delayed.queue) return redirect(url_for('admin.resolved'))
def unauthorized_handler(): return redirect(url_for('public.home'))
def promote(role_name=None): """Promote the user accessing this page.""" if not current_user().is_authenticated: return render_queue('error.html', code='Oops', message='You need to be logged in to promote an account!') part = Participant.query.filter_by( queue_id=g.queue.id, user_id=current_user().id ).one_or_none() n_owners = Participant.query.join(QueueRole).filter( QueueRole.name == 'Owner', Participant.queue_id == g.queue.id ).count() if part and part.role.name == 'Owner' and n_owners <= 1: return render_queue('error.html', code='Oops', message='You cannot demote yourself from owner until another owner has been added.') promotion_setting = g.queue.setting(name='self_promotion', default=None) if not promotion_setting or not promotion_setting.enabled: abort(404) tuples = [s.split(':') for s in promotion_setting.value.splitlines()] codes = dict((k.strip().lower(), v.strip()) for k, v in tuples) role_names = [role.name for role in g.queue.roles] if n_owners == 0: role_name = 'Owner' roles = [s.lower() for s in role_names + list(codes.keys())] if role_name and role_name.lower() not in roles: abort(404) if not role_name: return render_queue('roles.html', title='Promotion Form', message='Welcome. Please select a role below.', roles=[name for name in role_names if name.lower() in codes]) try: if n_owners == 0: code = '*' else: code = codes[role_name.lower()] except KeyError: abort(404) form = PromotionForm(request.form) if request.method == 'POST' or code == '*': if not (code == '*' or request.form['code'] == code): form.errors.setdefault('code', []).append('Incorrect code.') return render_queue('form.html', form=form, submit='Promote', back=url_for('queue.promote')) role = QueueRole.query.filter_by( name=role_name, queue_id=g.queue.id).one() part = Participant.query.filter_by( user_id=current_user().id, queue_id=g.queue.id).one_or_none() if part: part.update(role_id = role.id).save() else: Participant( user_id=current_user().id, queue_id=g.queue.id, role_id=role.id ).save() return render_queue('confirm.html', title='Promotion Success', message='You have been promoted to %s' % role_name, action='Onward', url=url_for('admin.home')) return render_queue('form.html', form=form, submit='Promote', back=url_for('queue.promote'))
def logout(): """Logout using globally defined logout procedure""" from quupod.public.views import logout return logout(home=url_for('queue.home', _external=True))
def login(): """Login using globally defined login procedure""" from quupod.public.views import login return login( home=url_for('queue.home', _external=True), login=url_for('queue.login', _external=True))
def unauthorized_handler(): """Redirect unauthorized users to the public queue home page.""" return redirect(url_for("public.home"))
def get_google_auth_flow(login: str=None) -> client.Flow: """Return Google auth flow object.""" return client.flow_from_clientsecrets( 'client_secrets.json', scope='openid profile email', redirect_uri=login or url_for('public.login', _external=True))