<commit_before>import { usingConnect, sql } from './pg-helpers'
import Promise from 'bluebird'
import crypto from 'crypto'
import scmp from 'scmp'

const pbkdf2 = Promise.promisify(crypto.pbkdf2, crypto);
const randomBytes = Promise.promisify(crypto.randomBytes, crypto);

function hashPassword(password, salt) {
  return pbkdf2(password, salt, 25000, 512, 'sha256')
    .then(hashed => new Buffer(hashed, 'binary').toString('hex'));
}

class User {
  constructor(userData) {
    this.id = userData.id;
    this.email = userData.email;
    this.passwordHash = userData.passwordhash;
    this.salt = userData.salt;
    this.isAdmin = userData.admin;
    this.active = userData.active;
  }

  validatePassword(password) {
    return hashPassword(password, this.salt)
      .then(hash => scmp(hash, this.passwordHash));
  }
}

function generatePasswordHashAndSalt(password) {
  return randomBytes(32)
    .then(buffer => buffer.toString('hex'))
    .then(salt => hashPassword(password, salt).then(passwordHash => [passwordHash, salt]));
}

export class UserRepository {
  constructor(connectionString) {
    this.connectionString = connectionString;
  }

  findById(id) {
    return usingConnect(this.connectionString, client =>
      client.queryAsync(sql`SELECT * FROM users WHERE id=${id}`)
        .then(result => result.rows.length === 0
          ? undefined
          : new User(result.rows[0])));
  }

  findByEmail(email) {
    return usingConnect(this.connectionString, client =>
      client.queryAsync(sql`SELECT * FROM users WHERE email=${email}`)
        .then(result => result.rows.length === 0
          ? undefined
          : new User(result.rows[0])));
  }

  updatePasswordById(id, password) {
    return generatePasswordHashAndSalt(password)
      .spread((passwordHash, salt) => usingConnect(this.connectionString, client =>
        client.queryAsync(sql`UPDATE users SET passwordHash=${passwordHash}, salt=${salt} WHERE id=${id}`)));
  }

  addUser(user) {
    const email = user.email;
    const isAdmin = user.isAdmin || false;

    return generatePasswordHashAndSalt(user.password)
      .spread((passwordHash, salt) => usingConnect(this.connectionString, client =>
        client.queryAsync(sql`INSERT INTO users (email, passwordHash, salt, admin) VALUES (${email}, ${passwordHash}, ${salt}, ${isAdmin})`)));
  }

  deleteById(id) {
    return usingConnect(this.connectionString, client => client.queryAsync(sql`DELETE FROM users WHERE id=${id}`));
  }<commit_msg>Change the profile deletion method to soft delete<commit_after>import { usingConnect, sql } from './pg-helpers'
import Promise from 'bluebird'
import crypto from 'crypto'
import scmp from 'scmp'

const pbkdf2 = Promise.promisify(crypto.pbkdf2, crypto);
const randomBytes = Promise.promisify(crypto.randomBytes, crypto);

function hashPassword(password, salt) {
  return pbkdf2(password, salt, 25000, 512, 'sha256')
    .then(hashed => new Buffer(hashed, 'binary').toString('hex'));
}

class User {
  constructor(userData) {
    this.id = userData.id;
    this.email = userData.email;
    this.passwordHash = userData.passwordhash;
    this.salt = userData.salt;
    this.isAdmin = userData.admin;
    this.active = userData.active;
  }

  validatePassword(password) {
    return hashPassword(password, this.salt)
      .then(hash => scmp(hash, this.passwordHash));
  }
}

function generatePasswordHashAndSalt(password) {
  return randomBytes(32)
    .then(buffer => buffer.toString('hex'))
    .then(salt => hashPassword(password, salt).then(passwordHash => [passwordHash, salt]));
}

export class UserRepository {
  constructor(connectionString) {
    this.connectionString = connectionString;
  }

  findById(id) {
    return usingConnect(this.connectionString, client =>
      client.queryAsync(sql`SELECT * FROM users WHERE id=${id}`)
        .then(result => result.rows.length === 0
          ? undefined
          : new User(result.rows[0])));
  }

  findByEmail(email) {
    return usingConnect(this.connectionString, client =>
      client.queryAsync(sql`SELECT * FROM users WHERE email=${email}`)
        .then(result => result.rows.length === 0
          ? undefined
          : new User(result.rows[0])));
  }

  updatePasswordById(id, password) {
    return generatePasswordHashAndSalt(password)
      .spread((passwordHash, salt) => usingConnect(this.connectionString, client =>
        client.queryAsync(sql`UPDATE users SET passwordHash=${passwordHash}, salt=${salt} WHERE id=${id}`)));
  }

  addUser(user) {
    const email = user.email;
    const isAdmin = user.isAdmin || false;

    return generatePasswordHashAndSalt(user.password)
      .spread((passwordHash, salt) => usingConnect(this.connectionString, client =>
        client.queryAsync(sql`INSERT INTO users (email, passwordHash, salt, admin) VALUES (${email}, ${passwordHash}, ${salt}, ${isAdmin})`)));
  }

  deleteById(id) {
    return usingConnect(this.connectionString, client =>
      client.queryAsync(sql`UPDATE users SET active='false' WHERE id=${id}`));
  }
{'fraction_non_alphanumeric': 0.1365262321144674, 'fraction_numerical': 0.00794912559618442, 'mean_word_length': 4.068479355488419, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, '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': '5903337', 'n_tokens_mistral': 1533, 'n_tokens_neox': 1472, 'n_words': 322}