<commit_before>/*
Passport-Live is a modern web app for schools that helps them manage passes.
    Copyright (C) 2017  <NAME>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

email: <EMAIL>
*/

/**
* @module js/security
*/

var r = require('rethinkdb');
var db = require('../../modules/db/index.js');
var config = require("config");
var moment = require("moment");
var shortid = require("shortid");
var oldApi = require("./index.js")
var typeCheck = require("type-check").typeCheck;
var utils = require("../passport-utils/index.js")


///PERMISSON KEYS
    



    /*
    Creates a short permission key 

    
    "permissions": a JSON object with a custom permission payload, Ex: userGroups
    "params": per Use case
    "timeout": Must be a Json object either:
    {
        tally: 5
    }
    OR 
    {
        time: Date object
    }
    */
    /**
     * Creates a New Permission Key.
     * @link module:js/security
     * @param {permissionKeyType} type - ENUM for the type of permission key this is.  Each may impose diffrent requirements.
     * @param {Object} permissions - Json tree of permissions.
     * @param {Object} params
     * @param {(undefined|Object)} timeout - When should the key become invalid.
     * @param {(undefined|number)} timeout.tally - Will become inactive after given number of uses.
     * @param {(undefined|Date|ISO)} timeout.time - Will become inactive after given time.
     * @returns {Promise}
     */
    exports.createPermissionKey = function(type, permissions, params, timeout) {
        return new Promise((resolve, reject) => {
            var ins = {}
            var key = shortid.generate() + shortid.generate();
            
            //console.log(parseInt(timeout.tally))
            console.log(timeout)
            /*if(timeout.time) {
                //format time to a general format
                timeout.time = moment(timeout.time).toISOString();
            } else if(timeout.tally) {
                if(isNaN(parseInt(timeout.tally))) {
                    var err = new Error("timeout.tally expected an int");
                    err.status = 400;
                    return reject(err)
                } else {
                    timeout.tally = parseInt(timeout.tally)
                }
            }*/
            if(!typeCheck("Maybe {tally: Maybe Number, time: Maybe ISODate | Date}", timeout, utils.typeCheck)) {
                var err = new TypeError("timeout expects an Object with the following types: \"Maybe {tally: Maybe Number, time: Maybe ISODate | Date}\"");
                    err.status = 400;
                    return reject(err)
            }

            if(timeout) {
                if(typeCheck("ISODate", timeout.time, utils.typeCheck)) {
                    timeout.time = r.ISO8601(timeout.time)
                }
                ins.timeout = timeout;
            }
            if(params) {
                ins.params = params;
            }
            if(permissions) {
                ins.permissions = permissions;
            }

            if(!typeCheck("permissionKeyType | Null", type, utils.typeCheck)) {
                var err = new TypeError("Type expected the \"permissionKeyType\" ENUM ");
                    err.status = 400;
                    return reject(err)
            }
            ins.key = key;
            ins.type = type;

            r.table("permissionKeys").insert(ins).run(db.conn(), function(err) {
                if(err) {
                    return reject(err);
                }
                return resolve(key);
            })
        })
    }//* @link module:js/security
    //* @memberof! js/security.newKey#
    //* @exports js/security/newKey
     /**
     * A set of wrappers for creating specific types of perm keys. 
     * @name newKey
     * @inner
     * @private
     * @memberof module:js/security
     * @property {Object} newKey
     * @property {function} newKey.newAccount - Creates a New Permission Key For New Accounts
     */
    var newKey = {};
     /**
     * Creates a New Permission Key For Creating New Accounts from the new account form and API
     * @function
     * @memberof module:js/security
     * @param {String[]} userGroups - Must only contain valid userGroup keys defined in the configs.
     * @param {(undefined|Object)} timeout - When should the key become invalid.
     * @param {(undefined|number)} timeout.tally - Will become inactive after given number of uses.
     * @param {(undefined|Date|string)} timeout.time - Will become inactive after given time.
     * @returns {Promise}
     */
    newKey.newAccount = function(userGroups, timeout) {
        return new Promise((resolve, reject) => {
            if(!typeCheck("[userGroup]", userGroups, utils.typeCheck)) {
                var err = new TypeError("userGroups must be an array of type \"userGroup\" strings.");
                err.status = 400;
                return reject(err);
            }
            //return reject(new Error("REJECTION"))
            return exports.createPermissionKey(exports.permissionKeyType.NEW_ACCOUNT, {userGroups: userGroups}, null, timeout).then(resolve).catch(reject)
        }) 
    }
    setTimeout(function() {
        //newKey.newAccount(["student", "teacher"], {tally: }) //["student", "teacher"]
        console.log(typeCheck("Date", new Date()))
        console.log(typeCheck("ISODate", "2017-11-10T02:41:57+00:00", utils.typeCheck))
        var date = new Date();
        date.setDate(date.getDate() + 1)
        console.log(typeCheck("Maybe {tally: Maybe Number, time: Maybe ISODate | Date}", {tally: 5, time: date}, utils.typeCheck))
        //newKey.newAccount(["student"], {time: "2017-11-10T02:41:57+00:00", tally:6})
        //newKey.newAccount(["student"], {time: date, tally:12})
    }, 1000);
    exports.newKey = newKey;


    //This checks to see if the Permission key is valid and returns a json object with the permissions.
    //Callback: done(err, perms)
    //SHould only return one
    /**
     * Checks a Permission Key.  It also may change the timeout field if on tally mode
     * @link module:js/security
     * @param {string} key - the key to check.
     * @param {function} done - Callback.
     */
exports.checkPermissionKey = function(key, done) {

    r.table("permissionKeys").filter({
        key: key,
    }).run(db.conn(), function(err, document) {
        if(err) {
            return done(err, null);
        }

        document.toArray(function(err, arr) {
            if(err) {
                return done(err)
            }
            console.log(arr)
            //Found key
            if(0<arr.length) {
                if(arr[0].timeout.time) {
                    if(moment(arr[0].timeout.time).isSameOrAfter()) {<commit_msg>Removed Debug Crap<commit_after>/*
Passport-Live is a modern web app for schools that helps them manage passes.
    Copyright (C) 2017  <NAME>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

email: <EMAIL>
*/

/**
* @module js/security
*/

var r = require('rethinkdb');
var db = require('../../modules/db/index.js');
var config = require("config");
var moment = require("moment");
var shortid = require("shortid");
var oldApi = require("./index.js")
var typeCheck = require("type-check").typeCheck;
var utils = require("../passport-utils/index.js")


///PERMISSON KEYS
    



    /*
    Creates a short permission key 

    
    "permissions": a JSON object with a custom permission payload, Ex: userGroups
    "params": per Use case
    "timeout": Must be a Json object either:
    {
        tally: 5
    }
    OR 
    {
        time: Date object
    }
    */
    /**
     * Creates a New Permission Key.
     * @link module:js/security
     * @param {permissionKeyType} type - ENUM for the type of permission key this is.  Each may impose diffrent requirements.
     * @param {Object} permissions - Json tree of permissions.
     * @param {Object} params
     * @param {(undefined|Object)} timeout - When should the key become invalid.
     * @param {(undefined|number)} timeout.tally - Will become inactive after given number of uses.
     * @param {(undefined|Date|ISO)} timeout.time - Will become inactive after given time.
     * @returns {Promise}
     */
    exports.createPermissionKey = function(type, permissions, params, timeout) {
        return new Promise((resolve, reject) => {
            var ins = {}
            var key = shortid.generate() + shortid.generate();
            
            //console.log(parseInt(timeout.tally))
            console.log(timeout)
            /*if(timeout.time) {
                //format time to a general format
                timeout.time = moment(timeout.time).toISOString();
            } else if(timeout.tally) {
                if(isNaN(parseInt(timeout.tally))) {
                    var err = new Error("timeout.tally expected an int");
                    err.status = 400;
                    return reject(err)
                } else {
                    timeout.tally = parseInt(timeout.tally)
                }
            }*/
            if(!typeCheck("Maybe {tally: Maybe Number, time: Maybe ISODate | Date}", timeout, utils.typeCheck)) {
                var err = new TypeError("timeout expects an Object with the following types: \"Maybe {tally: Maybe Number, time: Maybe ISODate | Date}\"");
                    err.status = 400;
                    return reject(err)
            }

            if(timeout) {
                if(typeCheck("ISODate", timeout.time, utils.typeCheck)) {
                    timeout.time = r.ISO8601(timeout.time)
                }
                ins.timeout = timeout;
            }
            if(params) {
                ins.params = params;
            }
            if(permissions) {
                ins.permissions = permissions;
            }

            if(!typeCheck("permissionKeyType | Null", type, utils.typeCheck)) {
                var err = new TypeError("Type expected the \"permissionKeyType\" ENUM ");
                    err.status = 400;
                    return reject(err)
            }
            ins.key = key;
            ins.type = type;

            r.table("permissionKeys").insert(ins).run(db.conn(), function(err) {
                if(err) {
                    return reject(err);
                }
                return resolve(key);
            })
        })
    }//* @link module:js/security
    //* @memberof! js/security.newKey#
    //* @exports js/security/newKey
     /**
     * A set of wrappers for creating specific types of perm keys. 
     * @name newKey
     * @inner
     * @private
     * @memberof module:js/security
     * @property {Object} newKey
     * @property {function} newKey.newAccount - Creates a New Permission Key For New Accounts
     */
    var newKey = {};
     /**
     * Creates a New Permission Key For Creating New Accounts from the new account form and API
     * @function
     * @memberof module:js/security
     * @param {String[]} userGroups - Must only contain valid userGroup keys defined in the configs.
     * @param {(undefined|Object)} timeout - When should the key become invalid.
     * @param {(undefined|number)} timeout.tally - Will become inactive after given number of uses.
     * @param {(undefined|Date|string)} timeout.time - Will become inactive after given time.
     * @returns {Promise}
     */
    newKey.newAccount = function(userGroups, timeout) {
        return new Promise((resolve, reject) => {
            if(!typeCheck("[userGroup]", userGroups, utils.typeCheck)) {
                var err = new TypeError("userGroups must be an array of type \"userGroup\" strings.");
                err.status = 400;
                return reject(err);
            }
            //return reject(new Error("REJECTION"))
            return exports.createPermissionKey(exports.permissionKeyType.NEW_ACCOUNT, {userGroups: userGroups}, null, timeout).then(resolve).catch(reject)
        }) 
    }
    /*
    setTimeout(function() {
        //newKey.newAccount(["student", "teacher"], {tally: }) //["student", "teacher"]
        console.log(typeCheck("Date", new Date()))
        console.log(typeCheck("ISODate", "2017-11-10T02:41:57+00:00", utils.typeCheck))
        var date = new Date();
        date.setDate(date.getDate() + 1)
        console.log(typeCheck("Maybe {tally: Maybe Number, time: Maybe ISODate | Date}", {tally: 5, time: date}, utils.typeCheck))
        //newKey.newAccount(["student"], {time: "2017-11-10T02:41:57+00:00", tally:6})
        //newKey.newAccount(["student"], {time: date, tally:12})
    }, 1000);*/
    exports.newKey = newKey;


    //This checks to see if the Permission key is valid and returns a json object with the permissions.
    //Callback: done(err, perms)
    //SHould only return one
    /**
     * Checks a Permission Key.  It also may change the timeout field if on tally mode
     * @link module:js/security
     * @param {string} key - the key to check.
     * @param {function} done - Callback.
     */
exports.checkPermissionKey = function(key, done) {

    r.table("permissionKeys").filter({
        key: key,
    }).run(db.conn(), function(err, document) {
        if(err) {
            return done(err, null);
        }

        document.toArray(function(err, arr) {
            if(err) {
                return done(err)
            }
            console.log(arr)
            //Found key
            if(0<arr.length) {
                if(arr[0].timeout.time) {
                    if(moment(arr[0].timeout.time).isSameOrAfter()) {
{'fraction_non_alphanumeric': 0.11635773237721553, 'fraction_numerical': 0.009470978216750102, 'mean_word_length': 2.068285595682856, 'pattern_counts': {'":': 6, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '3845912', 'n_tokens_mistral': 4163, 'n_tokens_neox': 3952, 'n_words': 1244}