Dashboard API explorer

/api/user/create-session (POST)

await global.api.user.CreateSession.post(req)
Located in Dashboard API

Returns object

Exceptions

These exceptions are thrown (NodeJS) or returned as JSON (HTTP) if you provide incorrect data or do not meet the requirements:

Exception Circumstances
invalid-username missing posted username
invalid-password missing posted password

Receives

API routes may receive parameters from the URL and POST supporting simple and multipart:

Field Value Required Type
remember hours, days optional POST

NodeJS source (edit on github)

If you see a problem with the source submit a pull request on Github.

const dashboard = require('../../../../index.js')

module.exports = {
  auth: false,
  post: async (req) => {
    if (!req || !req.body) {
      throw new Error('invalid-username')
    }
    if (!req.body.username || !req.body.username.length) {
      throw new Error('invalid-username')
    }
    if (!req.body.password || !req.body.password.length) {
      throw new Error('invalid-password')
    }
    let dashboardEncryptionKey = global.dashboardEncryptionKey
    let dashboardSessionKey = global.dashboardSessionKey
    if (req.server) {
      dashboardEncryptionKey = req.server.dashboardEncryptionKey || dashboardEncryptionKey
      dashboardSessionKey = req.server.dashboardSessionKey || dashboardSessionKey
    }
    const usernameHash = await dashboard.Hash.sha512Hash(req.body.username, dashboardEncryptionKey)
    const accountid = await dashboard.Storage.read(`${req.appid}/map/usernames/${usernameHash}`)
    if (!accountid) {
      if (global.minimumUsernameLength > req.body.username.length ||
          global.maximumUsernameLength < req.body.username.length) {
        throw new Error('invalid-username-length')
      }
      if (global.minimumPasswordLength > req.body.password.length ||
          global.maximumUsernameLength < req.body.password.length) {
        throw new Error('invalid-password-length')
      }
      throw new Error('invalid-username')
    }
    const passwordHash = await dashboard.StorageObject.getProperty(`${req.appid}/account/${accountid}`, 'passwordHash')
    const validPassword = await dashboard.Hash.bcryptHashCompare(req.body.password, passwordHash, dashboardEncryptionKey)
    if (!validPassword) {
      throw new Error('invalid-password')
    }
    const query = req.query
    req.query = { accountid }
    const account = await global.api.administrator.Account.get(req)
    req.query = query
    let expireSeconds
    switch (req.body.remember) {
      case 'hours':
        expireSeconds = 8 * 60 * 60
        break
      case 'days':
        expireSeconds = 30 * 24 * 60 * 60
        break
      default:
        expireSeconds = 20 * 60
        break
    }
    const sessionid = `session_${await dashboard.UUID.generateID()}`
    const sessionToken = dashboard.UUID.random(64)
    const sessionKey = await dashboard.StorageObject.getProperty(`${req.appid}/account/${account.accountid}`, 'sessionKey')
    const tokenHash = await dashboard.Hash.sha512Hash(`${accountid}/${sessionToken}/${sessionKey}/${dashboardSessionKey}`, dashboardEncryptionKey)
    const sessionInfo = {
      object: 'session',
      sessionid: sessionid,
      accountid: accountid,
      tokenHash: tokenHash,
      created: dashboard.Timestamp.now,
      expires: dashboard.Timestamp.now + expireSeconds,
      sessionKeyNumber: account.sessionKeyNumber
    }
    await dashboard.StorageObject.setProperty(`${req.appid}/account/${account.accountid}`, 'lastSignedIn', dashboard.Timestamp.now)
    await dashboard.Storage.write(`${req.appid}/session/${sessionid}`, sessionInfo)
    await dashboard.Storage.write(`${req.appid}/map/sessionids/${sessionid}`, accountid)
    await dashboard.StorageList.addMany({
      [`${req.appid}/sessions`]: sessionid,
      [`${req.appid}/account/sessions/${accountid}`]: sessionid
    })
    req.session = sessionInfo
    req.session.token = sessionToken
    return req.session
  }
}

Test source (edit on github)

Tests perform real HTTP requests against a running Dashboard server.

/* eslint-env mocha */
const TestHelper = require('../../../../test-helper.js')
const assert = require('assert')
const dashboard = require('../../../../index.js')

describe('/api/user/create-session', () => {
  describe('exceptions', () => {
    describe('invalid-username', () => {
      it('missing posted username', async () => {
        const req = TestHelper.createRequest('/api/user/create-session')
        req.body = {
          username: '',
          password: 'password'
        }
        let errorMessage
        try {
          await req.post()
        } catch (error) {
          errorMessage = error.message
        }
        assert.strictEqual(errorMessage, 'invalid-username')
      })
    })

    describe('invalid-password', () => {
      it('missing posted password', async () => {
        const req = TestHelper.createRequest('/api/user/create-session')
        req.body = {
          username: 'username',
          password: ''
        }
        let errorMessage
        try {
          await req.post()
        } catch (error) {
          errorMessage = error.message
        }
        assert.strictEqual(errorMessage, 'invalid-password')
      })
    })
  })

  describe('receives', () => {
    it('optional posted remember (hours|days)', async () => {
      const user = await TestHelper.createUser()
      const req = TestHelper.createRequest('/api/user/create-session')
      req.body = {
        username: user.account.username,
        password: user.account.password,
        remember: 'hours'
      }
      const session = await req.post()
      const hours = Math.ceil((session.expires - dashboard.Timestamp.now) / 60 / 60)
      assert.strictEqual(hours, 8)
      req.body = {
        username: user.account.username,
        password: user.account.password,
        remember: 'days'
      }
      const session2 = await req.post()
      const days = Math.ceil((session2.expires - dashboard.Timestamp.now) / 60 / 60 / 24)
      assert.strictEqual(days, 30)
    })
  })

  describe('returns', () => {
    it('object', async () => {
      const user = await TestHelper.createUser()
      const req = TestHelper.createRequest('/api/user/create-session')
      req.body = {
        username: user.account.username,
        password: user.account.password
      }
      req.filename = __filename
      req.saveResponse = true
      const session = await req.post()
      const minutes = Math.ceil((session.expires - dashboard.Timestamp.now) / 60)
      assert.strictEqual(minutes, 20)
    })
  })
})