{"size": 2948, "ext": "js", "max_stars_repo_path": "auth/models/user.js", "max_stars_repo_name": "danielesteban/blocks", "max_stars_repo_stars_event_min_datetime": "2020-05-27T02:19:42.000Z", "max_stars_repo_stars_event_max_datetime": "2022-02-09T03:12:08.000Z", "max_issues_repo_path": "auth/models/user.js", "max_issues_repo_name": "donPabloNow/blocks", "max_issues_repo_issues_event_min_datetime": "2020-05-29T17:48:49.000Z", "max_issues_repo_issues_event_max_datetime": "2021-09-02T13:01:22.000Z", "max_forks_repo_path": "auth/models/user.js", "max_forks_repo_name": "donPabloNow/blocks", "max_forks_repo_forks_event_min_datetime": "2020-07-06T23:25:37.000Z", "max_forks_repo_forks_event_max_datetime": "2021-12-09T02:09:10.000Z"}
{"max_stars_count": 47, "max_issues_count": 47, "max_forks_count": 9, "avg_line_length": 21.837037037, "max_line_length": 87, "alphanum_fraction": 0.5179782904}
const bcrypt = require('bcrypt');
const mongoose = require('mongoose');
const jwt = require('jsonwebtoken');
const sharp = require('sharp');

const sessionSecret = process.env.SESSION_SECRET || 'superunsecuresecret';
if (process.env.NODE_ENV === 'production' && sessionSecret === 'superunsecuresecret') {
  console.warn('\nSecurity warning:\nYou must provide a random SESSION_SECRET.\n');
}

const UserSchema = new mongoose.Schema({
  email: {
    type: String,
    lowercase: true,
    index: true,
    required: true,
    unique: true,
  },
  name: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    required: true,
  },
  skin: {
    type: Buffer,
    required: true,
  },
}, { timestamps: true });

UserSchema.pre('save', function onSave(next) {
  const user = this;
  const promises = [];
  if (user.isModified('password')) {
    promises.push(
      new Promise((resolve, reject) => (
        bcrypt.genSalt(5, (err, salt) => {
          if (err) return reject(err);
          return bcrypt.hash(user.password, salt, (err, hash) => {
            if (err) return reject(err);
            user.password = hash;
            return resolve();
          });
        })
      ))
    );
  }
  if (user.isModified('skin')) {
    promises.push(
      sharp(user.skin)
        .resize(64, 16)
        .png()
        .toBuffer()
        .then((skin) => {
          user.skin = skin;
        })
    );
  }
  if (!promises.length) {
    return next();
  }
  return Promise
    .all(promises)
    .then(() => next())
    .catch(next);
});

UserSchema.methods = {
  comparePassword(candidatePassword) {
    const user = this;
    return new Promise((resolve, reject) => (
      bcrypt.compare(candidatePassword, user.password, (err, isMatch) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(isMatch);
      })
    ));
  },
  getNewSession() {
    return {
      name: this.name,
      token: jwt.sign(
        {
          _id: this._id,
        },
        sessionSecret,
        { expiresIn: '7d' }
      ),
    };
  },
};

UserSchema.statics = {
  authenticate(req, res, next) {
    const User = mongoose.model('User');
    let token;
    if (req.headers.authorization) {
      const [type, value] = req.headers.authorization.split(' ');
      if (type === 'Bearer') {
        token = value;
      }
    }
    if (!token) {
      res.status(401).end();
      return;
    }
    jwt.verify(token, sessionSecret, (err, decoded) => {
      if (err) {
        res.status(401).end();
        return;
      }
      User
        .findOne({ _id: decoded._id })
        .select('_id')
        .then((user) => {
          if (!user) {
            res.status(401).end();
            return;
          }
          req.user = user;
          next();
        })
        .catch(() => (
          res.status(401).end()
        ));
    });
  },
};

module.exports = mongoose.model('User', UserSchema);
