Exemple #1
0
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))
Exemple #2
0
 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')
Exemple #3
0
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'))
Exemple #4
0
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'))
Exemple #5
0
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'))
Exemple #6
0
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")))
Exemple #7
0
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'))
Exemple #8
0
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)
Exemple #9
0
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())
Exemple #10
0
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())
Exemple #11
0
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')))
Exemple #12
0
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')
Exemple #13
0
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)
Exemple #14
0
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'))
Exemple #15
0
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')
Exemple #16
0
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'))
Exemple #17
0
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'))
Exemple #18
0
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))
Exemple #19
0
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'))
Exemple #20
0
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)
Exemple #21
0
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"))
Exemple #22
0
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)
Exemple #23
0
def requeue(inquiry_id):
    delayed = Inquiry.query.get(inquiry_id)
    delayed.unlock()
    emitQueuePositions(delayed)
    emitQueueInfo(delayed.queue)
    return redirect(url_for('admin.resolved'))
Exemple #24
0
def unauthorized_handler():
    return redirect(url_for('public.home'))
Exemple #25
0
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'))
Exemple #26
0
def logout():
    """Logout using globally defined logout procedure"""
    from quupod.public.views import logout
    return logout(home=url_for('queue.home', _external=True))
Exemple #27
0
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))
Exemple #28
0
def unauthorized_handler():
    """Redirect unauthorized users to the public queue home page."""
    return redirect(url_for("public.home"))
Exemple #29
0
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))