password.js 2.9 KB
Newer Older
DCloud_JSON's avatar
DCloud_JSON 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
const {
  getType
} = require('../../common/utils')
const crypto = require('crypto')

const PasswordHashMethod = {
  'hmac-sha1': function (content, secret) {
    const hmac = crypto.createHmac('sha1', secret.toString('ascii'))
    hmac.update(content)
    return hmac.digest('hex')
  }
}

class PasswordUtils {
  constructor ({
    passwordSecret
  } = {}) {
    const passwordSecretType = getType(passwordSecret)
    if (passwordSecretType === 'array') {
      this.passwordSecret = passwordSecret.sort((a, b) => {
        return a.version - b.version
      })
    } else if (passwordSecretType === 'string') {
      this.passwordSecret = [{ value: passwordSecret }]
    } else {
      throw new Error('Invalid password secret')
    }
  }

  getSecretByVersion (params = {}) {
    const {
      version
    } = params
    if (!version && version !== 0) {
      return this.getOldestSecret()
    }
    if (this.passwordSecret.length === 1) {
      return this.passwordSecret[0]
    }
    return this.passwordSecret.find(item => item.version === version)
  }

  getLastestSecret () {
    return this.passwordSecret[this.passwordSecret.length - 1]
  }

  getOldestSecret () {
    return this.passwordSecret[0]
  }

  checkUserPassword (params = {}) {
    const {
      password,
      passwordHash: passwordHashToCheck,
      passwordSecretVersion,
      autoRefresh = true
    } = params
    const currentPasswordSecret = this.getSecretByVersion({
      version: passwordSecretVersion
    })
    if (!currentPasswordSecret) {
      throw new Error('Invalid password version')
    }
    const {
      value: passwordSecret
    } = currentPasswordSecret
    const {
      passwordHash
    } = this.generatePasswordHash({
      password,
      passwordSecret,
      passwordSecretVersion
    })
    if (passwordHashToCheck !== passwordHash) {
      return {
        success: false
      }
    }
    let refreshPasswordInfo
    if (autoRefresh && passwordSecretVersion !== this.getLastestSecret().version) {
      refreshPasswordInfo = this.generatePasswordHash({
        password
      })
    }
    return {
      success: true,
      refreshPasswordInfo
    }
  }

  generatePasswordHash (params = {}) {
    let {
      password,
      passwordSecret,
      passwordSecretVersion
    } = params
    if (getType(password) !== 'string') {
      throw new Error('Invalid password')
    }
    password = password && password.trim()
    if (!password) {
      throw new Error('Invalid password')
    }
    if (!passwordSecret) {
      const lastestSecret = this.getLastestSecret()
      passwordSecret = lastestSecret.value
      passwordSecretVersion = lastestSecret.version
    }
    return {
      passwordHash: PasswordHashMethod['hmac-sha1'](password, passwordSecret),
      version: passwordSecretVersion
    }
  }
}

module.exports = PasswordUtils