<commit_before># -*- coding: utf-8 -*-

from collections import defaultdict
from functools import wraps
from io import StringIO
import csv

from flask import abort, current_app, render_template

from coaster.auth import current_auth
from lastuser_core.models import USER_STATUS, User, db

from .. import lastuser_ui


def requires_dashboard(f):
    """
    Decorator to require a login for the given view.
    """

    @wraps(f)
    def decorated_function(*args, **kwargs):
        if (
            not current_auth.is_authenticated
            or current_auth.user.buid
            not in current_app.config.get('DASHBOARD_USERS', [])
        ):
            abort(403)
        return f(*args, **kwargs)

    return decorated_function


@lastuser_ui.route('/dashboard')
@requires_dashboard
def dashboard():
    user_count = User.active_user_count()
    mau = (
        db.session.query('mau')
        .from_statement(
            db.text(
                '''
                SELECT COUNT(DISTINCT(user_session.user_id)) AS mau
                FROM user_session, "user"
                WHERE user_session.user_id = "user".id
                    AND "user".status = :status
                    AND user_session.accessed_at >= NOW() - INTERVAL '30 days'
                '''
            )
        )
        .params(status=USER_STATUS.ACTIVE)
        .first()[0]
    )

    return render_template('dashboard.html.jinja2', user_count=user_count, mau=mau)


@lastuser_ui.route('/dashboard/data/users_by_month.csv')
@requires_dashboard
def dashboard_data_users_by_month():
    users_by_month = (
        db.session.query('month', 'count')
        .from_statement(
            db.text(
                '''
                SELECT date_trunc('month', "user".created_at) AS month,
                    count(*) AS count
                FROM "user"<commit_msg>Use .scalar() when a single value is expected<commit_after># -*- coding: utf-8 -*-

from collections import defaultdict
from functools import wraps
from io import StringIO
import csv

from flask import abort, current_app, render_template

from coaster.auth import current_auth
from lastuser_core.models import USER_STATUS, User, db

from .. import lastuser_ui


def requires_dashboard(f):
    """
    Decorator to require a login for the given view.
    """

    @wraps(f)
    def decorated_function(*args, **kwargs):
        if (
            not current_auth.is_authenticated
            or current_auth.user.buid
            not in current_app.config.get('DASHBOARD_USERS', [])
        ):
            abort(403)
        return f(*args, **kwargs)

    return decorated_function


@lastuser_ui.route('/dashboard')
@requires_dashboard
def dashboard():
    user_count = User.active_user_count()
    mau = (
        db.session.query('mau')
        .from_statement(
            db.text(
                '''
                SELECT COUNT(DISTINCT(user_session.user_id)) AS mau
                FROM user_session, "user"
                WHERE user_session.user_id = "user".id
                    AND "user".status = :status
                    AND user_session.accessed_at >= NOW() - INTERVAL '30 days'
                '''
            )
        )
        .params(status=USER_STATUS.ACTIVE)
        .scalar()
    )

    return render_template('dashboard.html.jinja2', user_count=user_count, mau=mau)


@lastuser_ui.route('/dashboard/data/users_by_month.csv')
@requires_dashboard
def dashboard_data_users_by_month():
    users_by_month = (
        db.session.query('month', 'count')
        .from_statement(
            db.text(
                '''
                SELECT date_trunc('month', "user".created_at) AS month,
                    count(*) AS count
                FROM "user"
{'fraction_non_alphanumeric': 0.1029016657710908, 'fraction_numerical': 0.004030091348737238, 'mean_word_length': 2.115481171548117, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6694312', 'n_tokens_mistral': 1132, 'n_tokens_neox': 1077, 'n_words': 244}