auth/server.js

import { JsonApiServer } from '../json_api'
import { Token } from './token'
import { safeAccountId } from '../utils/safe_account_id'

/**
 * Facilitates interaction with the auth server.
 *
 * @class
 */
export class AuthServer extends JsonApiServer {
  /**
   * Create a new wallet server instance.
   *
   * @constructor
   * @param {ShelfNetwork} sdk Parent SDK instance.
   * @param {string} serverUrl wallet server URL.
   * @param {Object} opts
   * @param {boolean} [opts.allowHttp] Allow connecting to http servers, default: `false`. This must be set to false in production deployments!
   * @param {Object} [opts.proxy] Proxy configuration. Look [axios docs](https://github.com/axios/axios#request-config) for more info
   * @param {Object} [opts.httpBasicAuth] HTTP basic auth credentials. Look [axios docs](https://github.com/axios/axios#request-config) for more info.
   * @param {Object} [opts.customHeaders] Custom headers for request.
   * @param {boolean} [opts.withCredentials] Indicates whether or not cross-site Access-Control requests should be made using credentials.
   * @param {string} [opts.responseType='json'] Indicates the type of data that the server will respond with options are 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'.
   */
  constructor (sdk, serverUrl, opts = {}) {
    opts.alias = 'auth'
    super(sdk, serverUrl, opts)
  }

  /**
   * Get a JWT token using credentials.
   *
   * @param {string} email Email.
   * @param {string} password Password.
   * @param {string} [platformId] User's platform ID.
   *
   * @return {Promise.<Token>}
   */
  async getToken (email, password, platformId = null) {
    platformId = platformId || this._sdk.platformId

    const response = await this._makeCallBuilder()
      .appendUrlSegment('jwt')
      .post({
        data: {
          attributes: {
            email,
            password,
            platformId
          }
        }
      })

    return new Token(response.data.token)
  }

  /**
   * Refresh a JWT token.
   *
   * @param {string} [token] JWT token to be refreshed. The token attached to the sdk instance will be used by default.
   *
   * @return {Promise.<Token>}
   */
  async refreshToken (token) {
    token = token || this._sdk.token.rawJWT

    const response = await this._makeCallBuilder()
      .withCredentials()
      .appendUrlSegment('jwt')
      .patch({
        data: {
          attributes: {
            token
          }
        }
      })

    return new Token(response.data.token)
  }

  /**
   * Change the password.
   *
   * @param {string} oldPassword Old user's password.
   * @param {string} newPassword Desired password.
   *
   * @return {Promise.<AuthServerResponse>}
   */
  async changePassword (oldPassword, newPassword) {
    return this._makeCallBuilder()
      .appendUrlSegment('credentials')
      .withCredentials()
      .patch({
        data: {
          attributes: {
            oldPassword,
            newPassword
          }
        }
      })
  }

  /**
   * Request password recovery.
   *
   * @param {string} email User's email.
   *
   * @return {Promise.<AuthServerResponse>}
   */
  async requestRecovery (email, platformId = null) {
    platformId = platformId || this._sdk.platformId

    return this._makeCallBuilder()
      .appendUrlSegment('recovery_requests')
      .put({
        data: {
          type: 'recovery_requests',
          attributes: {
            email,
            platformId
          }
        }
      })
  }

  /**
   * Confirm the password recovery.
   *
   * @param {string} accountId User's account ID.
   * @param {string} token Recovery token from the email.
   * @param {string} newPassword Desired password.
   *
   * @return {Promise.<AuthServerResponse>}
   */
  async confirmRecovery (accountId, token, newPassword) {
    return this._makeCallBuilder()
      .appendUrlSegment('recovery_requests')
      .patch({
        data: {
          type: 'recovery_requests',
          id: accountId,
          attributes: {
            token,
            newPassword
          }
        }
      })
  }

  /**
   * Create credentials.
   *
   * @param {string} password Desired password.
   * @param {string} [accountId] User's account ID.
   * @return {Promise.<AuthServerResponse>}
   */
  async createCredentials (password, accountId = null) {
    accountId = safeAccountId(accountId, this._sdk)

    return this._makeCallBuilder()
      .withCredentials()
      .appendUrlSegment('credentials')
      .put({
        data: {
          type: 'credentials',
          id: accountId,
          attributes: {
            password
          }
        }
      })
  }
}