<commit_before>var fs = require('fs');
var file = 'test.db';
var exists = fs.existsSync(file);
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(file);
var bcrypt = require('bcrypt-nodejs');

if (!exists){
  console.log('Creating DB file.');
  fs.openSync(file, 'w');
  db.run('CREATE TABLE users (id INTEGER PRIMARY KEY, name VARCHAR(255), password VARCHAR(255), salt VARCHAR(255))');
  db.run('CREATE TABLE facts (user_id INTEGER, fact TEXT)');

  // Tables of all unique kanji, words and a junction table
  db.run('CREATE TABLE kanji (id INTEGER PRIMARY KEY, kanji TEXT UNIQUE)');
  db.run('CREATE TABLE words (id INTEGER PRIMARY KEY, word TEXT UNIQUE)');
  db.run('CREATE TABLE kanji_words (kanji_id INTEGER, word_id INTEGER, FOREIGN KEY(kanji_id) REFERENCES kanji(id), FOREIGN KEY(word_id) REFERENCES words(id))');

  // Tables of seen words/kanji on a per-user basis
  db.run('CREATE TABLE seen_words (user_id INTEGER, word_id INTEGER, FOREIGN KEY(user_id) REFERENCES users(id), FOREIGN KEY(word_id) REFERENCES words(id))');
  db.run('CREATE TABLE seen_kanji (user_id INTEGER, kanji_id INTEGER, FOREIGN KEY(user_id) REFERENCES users(id), FOREIGN KEY(kanji_id) REFERENCES kanji(id))');

  // Queue of items to study for each user
  db.run('CREATE TABLE study_queue (user_id INTEGER, queue TEXT, FOREIGN KEY(user_id) REFERENCES users(id))');
}


module.exports = fn = {

  checkUser: function(name, password, cb){

    // First, we get users with provided name
    db.all('SELECT id, name, password, salt FROM users WHERE name = ?', name, function(err, rows){
      if (err) {

        console.error(err);

      } else {

        // If no results, return
        if (!rows.length) {

          cb(null);

        } else {

          // Get salt, hashed password for user
          var salt = rows[0].salt;
          var hashedPassword = rows[0].password;

          // Generate hash from provided password and retrieved salt
          bcrypt.hash(password, salt, null, function(err, hash){

            // Check against DB values
            if (hash === hashedPassword){

              cb({
                id: rows[0].id,
                name: rows[0].name
              });

            } else {

              cb(null);

            }

          });

        }

      }

    });
      
  },

  addNewUser: function(name, password){

    // Generate salt for password
    bcrypt.genSalt(8, function(err, salt){

      if (err){
        console.error(err);
      }

      // Generate salted hash
      bcrypt.hash(password, salt, null, function(err, hash){

        if (err){
          console.error(err);
        }

        // Save name, hashed password and salt to DB
        db.run('INSERT INTO users (name, password, salt) VALUES (?, ?, ?)', name, hash, salt, function(err){
          // Create initial entry in study_queue
          var user_id = this.lastID;
          var q = JSON.stringify([0]);
          db.run('INSERT INTO study_queue (user_id, queue) VALUES (?, ?)', user_id, q);
        });<commit_msg>Added Bluebird versions of `addNewUser` and `checkUser`<commit_after>var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var file = 'test.db';
var exists = fs.existsSync(file);
var sqlite3 = Promise.promisifyAll(require('sqlite3').verbose());
var db = new sqlite3.Database(file);
var bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'));

if (!exists){
  console.log('Creating DB file.');
  fs.openSync(file, 'w');
  db.run('CREATE TABLE users (id INTEGER PRIMARY KEY, name VARCHAR(255), password VARCHAR(255), salt VARCHAR(255))');
  db.run('CREATE TABLE facts (user_id INTEGER, fact TEXT)');

  // Tables of all unique kanji, words and a junction table
  db.run('CREATE TABLE kanji (id INTEGER PRIMARY KEY, kanji TEXT UNIQUE)');
  db.run('CREATE TABLE words (id INTEGER PRIMARY KEY, word TEXT UNIQUE)');
  db.run('CREATE TABLE kanji_words (kanji_id INTEGER, word_id INTEGER, FOREIGN KEY(kanji_id) REFERENCES kanji(id), FOREIGN KEY(word_id) REFERENCES words(id))');

  // Tables of seen words/kanji on a per-user basis
  db.run('CREATE TABLE seen_words (user_id INTEGER, word_id INTEGER, FOREIGN KEY(user_id) REFERENCES users(id), FOREIGN KEY(word_id) REFERENCES words(id))');
  db.run('CREATE TABLE seen_kanji (user_id INTEGER, kanji_id INTEGER, FOREIGN KEY(user_id) REFERENCES users(id), FOREIGN KEY(kanji_id) REFERENCES kanji(id))');

  // Queue of items to study for each user
  db.run('CREATE TABLE study_queue (user_id INTEGER, queue TEXT, FOREIGN KEY(user_id) REFERENCES users(id))');
}


module.exports = fn = {

  checkUser2: function(name, password){
    // First, we get users with provided name
    return db.allAsync('SELECT id, name, password, salt FROM users WHERE name = ?', name)
      .then(function(rows){
        // Get salt, hashed password for user
        var salt = rows[0].salt;
        var hashedPassword = rows[0].password;
        // Generate hash from provided password and retrieved salt
        return bcrypt.hashAsync(password, salt, null)
          .then(function(hash){
            // Check against DB values
            if (hash === hashedPassword){
              return {
                id: rows[0].id,
                name: rows[0].name
              };
            } else {
              return null;
            }
          });
      })
      .catch(function(e){
        console.error(e);
      });
  },

  checkUser: function(name, password, cb){

    // First, we get users with provided name
    db.all('SELECT id, name, password, salt FROM users WHERE name = ?', name, function(err, rows){
      if (err) {

        console.error(err);

      } else {

        // If no results, return
        if (!rows.length) {

          cb(null);

        } else {

          // Get salt, hashed password for user
          var salt = rows[0].salt;
          var hashedPassword = rows[0].password;

          // Generate hash from provided password and retrieved salt
          bcrypt.hash(password, salt, null, function(err, hash){

            // Check against DB values
            if (hash === hashedPassword){

              cb({
                id: rows[0].id,
                name: rows[0].name
              });

            } else {

              cb(null);

            }

          });

        }

      }

    });
      
  },
  addNewUser2: function(name, password){
    // Generate salt for password
    return bcrypt.genSaltAsync(8)
      .then(function(salt){
        // Generate salted hash
        return bcrypt.hashAsync(password, salt, null)
          .then(function(hash){
            // Save name, hashed password and salt to DB
            return db.run('INSERT INTO users (name, password, salt) VALUES (?, ?, ?)', name, hash, salt)
              .then(function(){
                // Create initial entry in study_queue
                var user_id = this.lastID;
                var q = JSON.stringify([0]);
                return db.run('INSERT INTO study_queue (user_id, queue) VALUES (?, ?)', user_id, q)
                  .then(function(){
                    return true;
                  });
              });
          });
      })
      .catch(function(e){
        console.error(e);
      });
  },

  addNewUser: function(name, password){

    // Generate salt for password
    bcrypt.genSalt(8, function(err, salt){

      if (err){
        console.error(err);
      }

      // Generate salted hash
      bcrypt.hash(password, salt, null, function(err, hash){

        if (err){
          console.error(err);
        }

        // Save name, hashed password and salt to DB
        db.run('INSERT INTO users (name, password, salt) VALUES (?, ?, ?)', name, hash, salt, function(err){
          // Create initial entry in study_queue
          var user_id = this.lastID;
          var q = JSON.stringify([0]);
          db.run('INSERT INTO study_queue (user_id, queue) VALUES (?, ?)', user_id, q);
        });
{'fraction_non_alphanumeric': 0.12666666666666668, 'fraction_numerical': 0.005534591194968554, 'mean_word_length': 2.3032820938928125, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '2377613', 'n_tokens_mistral': 2495, 'n_tokens_neox': 2324, 'n_words': 708}