3.8.7 โ€ข Published 6 years ago

@hoodie/account-server-api v3.8.7

Weekly downloads
43
License
Apache-2.0
Repository
github
Last release
6 years ago

hoodie-account-server-api

Account JavaScript API backed by PouchDB

Build Status Coverage Status Dependency Status devDependency Status

@hoodie/account-server-api is a JavaScript API to manage user accounts and authentication backed by PouchDB. Features include account profiles and tokens.

Example

var AccountApi = require('@hoodie/account-server-api')
var PouchDB = require('pouchdb')

var api = new AccountApi({
  PouchDB: PouchDB,
  usersDb: 'my-users-db',
  secret: 'secret123'
})

API

@hoodie/account-server-api is a subset of hoodie-account-client/admin. If you see any inconsistencies, please create an issue

Constructor

new AccountApi(options)

Returns an api instance.

Examples

var PouchDB = require('pouchdb')
var api = new AccountApi({
  PouchDB: PouchDB,
  secret: 'secret123',
  usersDb: 'my-users-db'
})

api.sessions.add()

Admins can create a session for any user.

admin.sessions.add(options)

Resolves with sessionProperties

{
  id: 'session123',
  // account is always included
  account: {
    id: 'account456',
    username: 'pat@example.com'
  }
}

Rejects with:

Examples

// create session if patโ€™s password is "secret"
admin.sessions.add({
  account: {
    username: 'pat',
    password: 'secret'
  }
}).then(function (sessionProperties) {
  var sessionId = sessionProperties.id
  var username = sessionProperties.account.username
}).catch(function (error) {
  console.error(error)
})
// create session for pat
admin.sessions.add({
  account: {
    username: 'pat'
  }
}).then(function (sessionProperties) {
  var sessionId = sessionProperties.id
  var username = sessionProperties.account.username
}).catch(function (error) {
  console.error(error)
})
// create session using a one-time auth token
admin.sessions.add({
  account: {
    token: 'secrettoken123'
  }
}).then(function (sessionProperties) {
  var sessionId = sessionProperties.id
  var username = sessionProperties.account.username
}).catch(function (error) {
  console.error(error)
})

api.sessions.find()

admin.sessions.find(sessionId)

Resolves with sessionProperties

{
  id: 'session123',
  // account is always included
  account: {
    id: 'account456',
    username: 'pat@example.com'
    // admin accounts have no profile
  }
}

Rejects with:

Example

admin.sessions.find('abc4567').then(function (sessionProperties) {
  console.log('Session is valid.')
}).catch(function (error) {
  if (error.name === 'NotFoundError') {
    console.log('Session is invalid')
    return
  }

  console.error(error)
})

api.sessions.findAll()


๐Ÿ• TO BE DONE: #27


admin.sessions.findAll(options)

Resolves with Array of sessionProperties

[{
  id: 'session123',
  account: {
    id: 'account456',
    username: 'pat@example.com'
  }
}, {
  id: 'session456',
  account: {
    id: 'account789',
    username: 'sam@example.com'
  }
}]

Rejects with:

Example

admin.sessions.findAll()
  .then(function (sessions) {})
  .catch(function (error) {
    console.error(error)
  })

api.sessions.remove()

admin.sessions.remove(sessionId)

Resolves with sessionProperties

{
  id: 'session123',
  account: {
    id: 'account456',
    username: 'pat@example.com'
  }
}

Rejects with:

Example

admin.sessions.remove('abc4567')
  .then(function (sessionProperties) {})
  .catch(function (error) {
    console.error(error)
  })

NOTE: #27 Deleting a Session does not really have an effect today, as no session state is kept, and sessions are hash based


api.sessions.removeAll()


๐Ÿ• TO BE DONE: #27


admin.sessions.removeAll(options)

Resolves with Array of sessionProperties

[{
  id: 'session123',
  account: {
    id: 'account456',
    username: 'pat@example.com'
  }
}, {
  id: 'session456',
  account: {
    id: 'account789',
    username: 'sam@example.com'
  }
}]

Rejects with:

Example

admin.sessions.removeAll()
  .then(function (sessions) {})
  .catch(function (error) {
    if (error.name === 'NotFoundError') {
      console.log('Session is invalid')
      return
    }

    console.error(error)
  })

api.accounts.add()

admin.accounts.add(object)

Resolves with accountProperties:

{
  "id": "account123",
  "username": "pat",
  "createdAt": "2016-01-01T00:00:00.000Z",
  "updatedAt": "2016-01-01T00:00:00.000Z",
  "profile": {
    "fullname": "Dr. Pat Hook"
  }
}

Rejects with:

Example

admin.accounts.add({
  username: 'pat',
  password: 'secret',
  profile: {
    fullname: 'Dr Pat Hook'
  }
})
  .then(function (accountProperties) {})
  .catch(function (error) {
    console.error(error)
  })

api.accounts.find()

An account can be looked up by account.id, username or token.

  • If a username property is present, it will be looked up by username
  • If an id property is present, it will be looked up by accountId
  • If an token property is present, it will be looked up by token
admin.accounts.find(idOrObject, options)

Resolves with accountProperties:

{
  "id": "account123",
  "username": "pat",
  "createdAt": "2016-01-01T00:00:00.000Z",
  "updatedAt": "2016-01-01T00:00:00.000Z",
  // if options.include === 'profile'
  "profile": {
    "fullname": "Dr. Pat Hook"
  }
}

Rejects with:

Example

admin.accounts.find({ username: 'pat' })
  .then(function (accountProperties) {})
  .catch(function (error) {
    console.error(error)
  })

api.accounts.findAll()

admin.accounts.findAll(options)

Resolves with Array of accountProperties

[{
  "id": "account123",
  "username": "pat",
  "createdAt": "2016-01-01T00:00:00.000Z",
  "updatedAt": "2016-01-01T00:00:00.000Z",
  // if options.include === 'profile'
  "profile": {
    "fullname": "Dr. Pat Hook"
  }
}, {
  "id": "account456",
  "username": "sam",
  "createdAt": "2016-01-01T00:00:00.000Z",
  "updatedAt": "2016-01-01T00:00:00.000Z",
  // if options.include === 'profile'
  "profile": {
    "fullname": "Lady Samident"
  }
}]

Rejects with:

Example

admin.accounts.findAll()
  .then(function (accounts) {})
  .catch(function (error) {
    console.error(error)
  })

api.accounts.update()

An account can be looked up by account.id, username or token.

  • If a username property is present, it will be looked up by username
  • If an id property is present, it will be looked up by accountId
  • If an token property is present, it will be looked up by token
admin.accounts.update(idOrObject, changedProperties, options)
// or
admin.accounts.update(accountProperties, options)

Resolves with accountProperties:

{
  "id": "account123",
  "username": "pat",
  "createdAt": "2016-01-01T00:00:00.000Z",
  "updatedAt": "2016-01-01T00:00:00.000Z",
  // if options.include === 'profile'
  "profile": {
    "fullname": "Dr. Pat Hook"
  }
}

Rejects with:

Examples

admin.accounts.update({ username: 'pat' }, { foo: 'bar' })
  .then(function (accountProperties) {})
  .catch(function (error) {
    console.error(error)
  })
// same as
admin.accounts.update({ username: 'pat', foo: 'bar' })
  .then(function (accountProperties) {})
  .catch(function (error) {
    console.error(error)
  })

api.accounts.updateAll()


๐Ÿ• TO BE DONE: create issue and link it here


api.accounts.remove()

An account can be looked up by account.id, username or token.

  • If a username property is present, it will be looked up by username
  • If an id property is present, it will be looked up by accountId
  • If an token property is present, it will be looked up by token
admin.accounts.remove(idOrObject, changedProperties, options)
// or
admin.accounts.remove(accountProperties, options)

Resolves with accountProperties:

{
  "id": "account123",
  "username": "pat",
  "createdAt": "2016-01-01T00:00:00.000Z",
  "updatedAt": "2016-02-01T00:00:00.000Z",
  "deletedAt": "2016-03-01T00:00:00.000Z",
  // if options.include === 'profile'
  "profile": {
    "fullname": "Dr. Pat Hook"
  }
}

Rejects with:

Examples

admin.accounts.remove({ username: 'pat' }, { reason: 'foo bar' })
  .then(function (accountProperties) {})
  .catch(function (error) {
    console.error(error)
  })
// same as
admin.accounts.remove({ username: 'pat', reason: 'foo bar' })
  .then(function (accountProperties) {})
  .catch(function (error) {
    console.error(error)
  })

api.accounts.removeAll()


๐Ÿ• TO BE DONE: create issue and link it here


api.requests.add()


๐Ÿ• TO BE DONE: create issue and link it here


admin.requests.add({
  type: 'passwordreset',
  email: 'pat@example.com'
})

Resolves with

{
  id: 'request123',
  type: 'passwordreset',
  email: 'pat@example.com'
}

api.requests.find()


๐Ÿ• TO BE DONE: create issue and link it here


admin.requests.find('token123')
admin.requests.find({id: 'token123'})

api.requests.findAll()


๐Ÿ• TO BE DONE: create issue and link it here


admin.requests.findAll()

api.requests.remove()


๐Ÿ• TO BE DONE: create issue and link it here


admin.requests.remove('token123')
admin.requests.find({id: 'token123'})

api.requests.removeAll()


๐Ÿ• TO BE DONE: create issue and link it here


api.account()

The admin.account method returns a scoped API for one account, see below

var account = admin.account(idOrObject)

Examples

admin.account('account123')
admin.account({id: 'account123'})
admin.account({username: 'pat@example.com'})
admin.account({token: 'token456'})

api.account().profile.find()


๐Ÿ• TO BE DONE: create issue and link it here


admin.account(idOrObject).profile.find()

resolves with profileProperties

{
  "id": "account123-profile",
  "fullname": "Dr Pat Hook",
  "address": {
    "city": "Berlin",
    "street": "AdalberststraรŸe 4a"
  }
}

api.account().profile.update()


๐Ÿ• TO BE DONE: create issue and link it here


admin.account(idOrObject).profile.update(changedProperties)

resolves with profileProperties

{
  "id": "account123-profile",
  "fullname": "Dr Pat Hook",
  "address": {
    "city": "Berlin",
    "street": "AdalberststraรŸe 4a"
  }
}

api.account().tokens.add()

admin.account('account123').tokens.add(properties)

resolves with tokenProperties

{
  "id": "token123",
  "type": "passwordreset",
  "accountId": "account123",
  "contact": "pat@example.com",
  "createdAt": "2016-01-01T00:00:00.000Z"
}

Rejects with:

Example

admin.account({username: 'pat@example.com'}).account.tokens.add({
  type: 'passwordreset',
  email: 'pat@example.com'
})

api.account().tokens.find()

admin.account(idOrObject).tokens.find(id)

resolves with tokenProperties

{
  "id": "token123",
  "type": "passwordreset",
  "accountId": "account123",
  "contact": "pat@example.com",
  "createdAt": "2016-01-01T00:00:00.000Z"
}

Rejects with:

Example

admin.account({username: 'pat'}).tokens.find('token123')

api.account().tokens.findAll()


๐Ÿ• TO BE DONE: create issue and link it here


admin.account(idOrObject).tokens.findAll(options)

resolves with array of tokenProperties

[{
  "id": "token123",
  "type": "passwordreset",
  "accountId": "account123",
  "contact": "pat@example.com",
  "createdAt": "2016-01-01T00:00:00.000Z"
}, {
  "id": "token456",
  "type": "session",
  "accountId": "account123",
  "createdAt": "2016-01-02T00:00:00.000Z"
}]

Example

admin.account({username: 'pat'}).tokens.findAll()
  .then(function (tokens) {})
  .catch(function (error) {
    console.error(error)
  })

api.account().tokens.remove()


๐Ÿ• TO BE DONE: create issue and link it here


admin.account(idOrObject).tokens.remove(idOrObject)

resolves with tokenProperties

{
  "id": "token123",
  "type": "passwordreset",
  "accountId": "account123",
  "contact": "pat@example.com",
  "createdAt": "2016-01-01T00:00:00.000Z"
}

Example

admin.account({username: 'pat'}).tokens.removes('token123')

api.account().roles.add()


๐Ÿ• TO BE DONE: create issue and link it here


admin.account(idOrObject).roles.add(name)

resolves with roleName

"mycustomrole"

Example

admin.account({username: 'pat'}).roles.add('mycustomrole')

api.account().roles.findAll()


๐Ÿ• TO BE DONE: create issue and link it here


admin.account(idOrObject).roles.add(name)

resolves with array of roleNames

["mycustomrole", "myothercustomrole"]

Example

admin.account({username: 'pat'}).roles.findAll()
  .then(function (roles) {})
  .catch(function (error) {
    console.error(error)
  })

api.account().roles.remove()


๐Ÿ• TO BE DONE: create issue and link it here


admin.account(idOrObject).roles.remove(name)

resolves with roleName

"mycustomrole"

Example

admin.account({username: 'pat'}).roles.remove('mycustomrole')

Events


๐Ÿ• TO BE DONE: #35


Events emitted on

  • admin.sessions
  • admin.accounts
  • admin.requests
admin.sessions.on('change', function (eventName, session) {})
admin.accounts.on('update', function (account) {})
admin.requests.on('remove', handler)

Contributing

Have a look at the Hoodie project's contribution guidelines. If you want to hang out you can join our Hoodie Community Chat.

Testing

Local setup

git clone https://github.com/hoodiehq/hoodie-account-server-api.git
cd hoodie-account-server-api
npm install

Run all tests and code style checks

npm test

If you want to run a single test you can do it with

./node_modules/.bin/tap test/unit/sessions/remove-test.js

License

Apache 2.0

3.8.7

6 years ago

3.8.6

6 years ago

3.8.5

7 years ago

3.8.4

7 years ago

3.8.3

7 years ago

3.8.2

7 years ago

3.8.1

7 years ago

3.8.0

7 years ago

3.7.1

7 years ago

3.7.0

7 years ago

3.6.5

7 years ago

3.6.4

7 years ago

3.6.3

7 years ago

3.6.2

7 years ago

3.6.1

7 years ago

3.6.0

7 years ago

3.5.0

7 years ago

3.4.0

7 years ago

3.3.3

7 years ago

3.3.2

7 years ago

3.3.1

7 years ago

3.3.0

7 years ago

3.2.1

7 years ago

3.2.0

7 years ago

3.1.0

7 years ago

3.0.4

8 years ago

3.0.3

8 years ago

3.0.2

8 years ago

3.0.1

8 years ago

3.0.0

8 years ago

2.2.0

8 years ago

2.1.1

8 years ago

2.1.0

8 years ago

2.0.0

8 years ago

1.0.0

8 years ago