<commit_before>'use strict';

const _ = require('lodash');

const boom = require('boom');
const deckDB = require('../database/deckDatabase');
const userService = require('../services/user');
const querystring = require('querystring');

let self = module.exports = {

    // TODO improve the response object
    listDecks: function(request, reply) {
        let options = _.pick(request.query, 'user', 'idOnly', 'rootsOnly', 'roles', 'sort', 'page', 'pageSize');

        if(request.query.roles){

            let roles = request.query.roles.split(',');

            if(request.auth.credentials && roles.includes('editor') && 
                request.auth.credentials.userid === request.query.user){

                return userService.fetchGroupsForUser(request.query.user, request.auth.token).then( (usergroups) => {
                    let conditions = [{
                        'editors.groups.id': { $in: usergroups }
                    },
                    {
                        'editors.users.id': request.query.user
                    }];
                    if(request.query.user && roles.includes('owner')){
                        conditions.push({
                            user: request.query.user
                        });
                    }

                    return countAndList({ $or: conditions }, options).then( (response) => {
                        reply(response);
                    });
                    
                }).catch( (err) => {
                    if (err.isBoom) return reply(err);
                    request.log('error', err);
                    reply(boom.badImplementation());
                });
            }
        }

        let query = {};
        if(request.query.user){
            query = {
                user: request.query.user
            };
        }

        return countAndList(query, options).then( (response) => {
            reply(response);
        }).catch((err) => {
            if (err.isBoom) return reply(err);
            request.log('error', err);
            reply(boom.badImplementation());
        });
    },

    getDeckOwners: function(request, reply) {
        let query = {};
        if (request.query.user) {
            query.user = { $in: request.query.user.split(',').map((u) => parseInt(u)) };
        }

        deckDB.getDeckOwners(query).then((users) => {
            reply(users);
        }).catch((err) => {
            request.log('error', err);
            reply(boom.badImplementation());
        });

    },

};

function countAndList(query, options){
    options.countOnly = true;
    return deckDB.list(query, options).then( (result) => {

        delete options.countOnly;
        let totalCount = (result.length === 0) ? 0 : result[0].totalCount;

        return deckDB.list(query, options).then((decks) => {

            // form links for previous and next results
            let links = {};

            if(options.page > 1){
                options.page = options.page - 1;
                links.previous = `/decks?${querystring.stringify(options)}`;
            }

            if(options.page * options.pageSize < totalCount){
                options.page = options.page + 1;
                links.next = `/decks?${querystring.stringify(options)}`;
            }

            let items = decks.map((deck) => {
                return (options.idOnly) ? { _id: deck._id } : transform(deck);
            });

            if(options.idOnly){
                return items;
            }

            let response = {};
            response._meta = {
                page: options.page, 
                pageSize: options.pageSize,
                totalCount: totalCount,
                sort: options.sort,
                links: links
            };
            response.items = items;
            return response;
        });
    });
}

function transform(deck){
    let metadata = {};
    metadata._id = deck._id;
    metadata.timestamp = deck.timestamp;
    metadata.description = deck.description;
    metadata.lastUpdate = deck.lastUpdate;
    metadata.tags = deck.tags;<commit_msg>Fix returned _meta.page in /decks route<commit_after>'use strict';

const _ = require('lodash');

const boom = require('boom');
const deckDB = require('../database/deckDatabase');
const userService = require('../services/user');
const querystring = require('querystring');

let self = module.exports = {

    // TODO improve the response object
    listDecks: function(request, reply) {
        let options = _.pick(request.query, 'user', 'idOnly', 'rootsOnly', 'roles', 'sort', 'page', 'pageSize');

        if(request.query.roles){

            let roles = request.query.roles.split(',');

            if(request.auth.credentials && roles.includes('editor') && 
                request.auth.credentials.userid === request.query.user){

                return userService.fetchGroupsForUser(request.query.user, request.auth.token).then( (usergroups) => {
                    let conditions = [{
                        'editors.groups.id': { $in: usergroups }
                    },
                    {
                        'editors.users.id': request.query.user
                    }];
                    if(request.query.user && roles.includes('owner')){
                        conditions.push({
                            user: request.query.user
                        });
                    }

                    return countAndList({ $or: conditions }, options).then( (response) => {
                        reply(response);
                    });
                    
                }).catch( (err) => {
                    if (err.isBoom) return reply(err);
                    request.log('error', err);
                    reply(boom.badImplementation());
                });
            }
        }

        let query = {};
        if(request.query.user){
            query = {
                user: request.query.user
            };
        }

        return countAndList(query, options).then( (response) => {
            reply(response);
        }).catch((err) => {
            if (err.isBoom) return reply(err);
            request.log('error', err);
            reply(boom.badImplementation());
        });
    },

    getDeckOwners: function(request, reply) {
        let query = {};
        if (request.query.user) {
            query.user = { $in: request.query.user.split(',').map((u) => parseInt(u)) };
        }

        deckDB.getDeckOwners(query).then((users) => {
            reply(users);
        }).catch((err) => {
            request.log('error', err);
            reply(boom.badImplementation());
        });

    },

};

function countAndList(query, options){
    options.countOnly = true;
    return deckDB.list(query, options).then( (result) => {

        delete options.countOnly;
        let totalCount = (result.length === 0) ? 0 : result[0].totalCount;

        return deckDB.list(query, options).then((decks) => {

            // form links for previous and next results
            let links = {};
            let page = options.page;

            if(options.page > 1){
                options.page = page - 1;
                links.previous = `/decks?${querystring.stringify(options)}`;
            }

            if(options.page * options.pageSize < totalCount){
                options.page = page + 1;
                links.next = `/decks?${querystring.stringify(options)}`;
            }

            let items = decks.map((deck) => {
                return (options.idOnly) ? { _id: deck._id } : transform(deck);
            });

            if(options.idOnly){
                return items;
            }

            let response = {};
            response._meta = {
                page: page, 
                pageSize: options.pageSize,
                totalCount: totalCount,
                sort: options.sort,
                links: links
            };
            response.items = items;
            return response;
        });
    });
}

function transform(deck){
    let metadata = {};
    metadata._id = deck._id;
    metadata.timestamp = deck.timestamp;
    metadata.description = deck.description;
    metadata.lastUpdate = deck.lastUpdate;
    metadata.tags = deck.tags;
{'fraction_non_alphanumeric': 0.1374378863168101, 'fraction_numerical': 0.0014543691673736517, 'mean_word_length': 1.499091459721381, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, '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': '7637090', 'n_tokens_mistral': 2230, 'n_tokens_neox': 2098, 'n_words': 405}