ssb-profile
A helper module for reading and writing to "profile threads" in scuttlebutt
Last updated 19 days ago by chereseeriepa .
AGPL-3.0 · Repository · Bugs · Original npm · Tarball · package.json
$ cnpm install ssb-profile 
SYNC missed versions from official npm registry.

ssb-profile

An ssb-server plugin for creating, reading, updating profiles in scuttlebutt

Example Usage

const Server = require('ssb-server')
const Config = require('ssb-config/inject')

const config = Config({})

const server = Server
  .use(require('ssb-master'))
  .use(require('ssb-backlinks'))
  .use(require('ssb-profile')) // <<<<<<
  .call(null, config)

const type = 'person'
const details = {
  preferredName: {set: 'Ben'},
  description: {set: 'Kia orano, Ko te Mata Atau te waka'}
}

server.profile.create(type, details, (err, profileId) => {
  // ...
})
// later:
server.profile.get(profileId, (err, profile) => {
  // ...
})

// or:
const update = {
  preferredName: {set: 'Ben'},
  description: {set: 'Kia orano, Ko te Mata Atau te waka, Ko Ngati nurou iwi'},
  altNames: {
    add: [ 'Nootai Maui' ] // see notes about why the syntax is different here
  }
}

server.profile.update(profileId, update, (err, updateMsg) => {
  // ...
})

Requirements

An ssb-server with the following plugins:

  • ssb-backlinks

API

server.profile.create(type, update, cb)

creates a new profile and describes details you'd like to set on it

  • type String - describes type of profile,
    • e.g. "community" would lead to a message of type profile/community being published
  • update Object - allows you to describe an transformation from an "empty" profile to something with details. (see below for details)
  • cb Function - a callback with signature (err, profileId)

update format A "valid" update is any Object which has some (or all) of the following fields, along with appropriate transformation value: "recognised properties" :

{
  preferredName: {set: String},
  legalName: {set: String},
  altNames: {
    add: [String, String, ..],
    remove: [String, ...]
  },
  description: {set: String},
  address: {set:String},
  location: {set: String},
  phone: {set: String},
  email: {set: String},
  profession: {set: String},

  gender: {set: Gender},
  aliveInterval: {set: EdtfIntervalString},
  deceased: {set: Boolean},
  birthOrder: {set: Int},
  avatarImage: {set: Image},
  headerImage: {set: Image},
  tombstone: {set: Tombstone},

  authors: {
    add: [FeedId, ALL_AUTHORS],
    remove: [FeedId, ALL_AUTHORS] // NOTE: not available on update
  },
  repcs: [FeedId],
  allowPublic: Boolean
}

Notes:

  • this is deliberatly verbose + explicit (for clarity)
  • Transformations which use "set" are for field which we expect to have just 1 value. This transformation over-writes previous data.
  • Transformations which use "add"/ "remove" are for fields which might have multiple values. Internally this behaves likes a Set, i.e. multiple additions of "Ben" will only be counted once.
  • For any of these fields, if null is the value (e.g. {legalName: null}), this treated as the identity transformation (i.e. do not change this field)
  • Gender = String male | female | other | unknown
  • EdtfIntervalString - see edtf module and library of congress spec
  • UnixTime = Integer microseconds since 00:00 1st Jan 1970 (can be negative, read more)
  • All image properties expect values of type Image - an Object of shape:
    {
      blob: Blob,        // the content address for the blob (with prefex &)
      mimeType: String,  // mimetype of the image
      unbox: UnboxKey,   // (optional) a String for unboxing the blob if encrypted
      size: Number,      // (optional) size of the image in bytes
      width: Number,     // (optional) width of image in pixels
      height: Number     // (optional) height of image in pixels
    }
    
  • type Tombstone is either null OR an Object of shape:
    {
      date: UnixTime,  // an Integer indicating microseconds from 1st Jan 1970, can be negative!
      reason: String   // (optional)
    }
    
  • recps is a special scuttlebutt property, short for "recipients". Adding this means the profile will automatically be encrypted so only the FeedId listed in the recps Array will be able to read this profile.
  • allowPublic is an option you can provide to explicitly bypass ssb-recps-guard (which will default block all public records being published if installed)
  • authors contains two arrays (add, remove) for adding and removing authors to the set. Authors are of the form feedId or *:
    • FeedId - updates from this author will be valid
    • * - updates by all authors will be valid
    • NOTE: authors are valid until they are removed from the set. When this feedId, it overrides all authors until it is removed
    • Any updates that arent from a valid author are classed as invalid and wont be returned when using the get method

server.profile.update(profileId, update, cb)

Update the details for a profile

  • profileId String - the cypherlink for the profile (the key / hash of the root message for the profile)
  • update Object - describes updates to the profile (same format as that described in server.profile.create)
    • NOTE: the recps for updates are automatically inherited from the root message, so this field is not valid for this method.
  • cb Function - a callback with signature (err, updateMsg)

server.profile.get(profileId, cb)

  • profileId String - the cypherlink for the profile (the key / hash of the root message for the profile)
  • cb Function - a callback with signature (err, profile)

Because there might be multiple offline edits to a profile which didn't know bout one-another, it's possible for divergence to happen:

   A   (the root message)
   |
   B   (an edit after A)
  / \
 C   D (two concurrent edits after B)

profile is an Object which maps the key of a each latest edit to the state it perceives the profile to be in! So for that prior example:

// profile
{
  key: MessageId, // the root message of the profile tangle, aka profileId
  recps: [Recp],  // recipients
  states: [
    { head: C, state: stateC },
    { head: D, state: stateD },
  ]
}

where

  • recps Array - the collection of private recipients who can read the profile
    • if it's a public profile this is an empty array
    • Recp might be a FeedId or a GroupId (if this profile was published in a private-group
  • states Array - the one / multiple states in which the profile is in (the is possible with multple editors:
    • head MessageId is the key of the message which is the most recent edit
    • state is an object which shows what the state of the profile is (from the perspective of a person standing at that particular head)
    • has form which looks like:
// state
{
  type: String,
  preferredName: String,
  legalName: String,
  altNames: [String, String, ...],
  gender: Gender,
  aliveInterval: EdtfIntervalString,
  deceased: Boolean,
  birthOrder: Int,
  description: String,
  address: String,
  location: String,
  phone: String,
  email: String,
  profession: String,
  avatarImage: Image,
  headerImage: Image,

  authors: {
    [FeedId]: [
      { start: Integer, end: Integer }
    ]
  },
  tombstone: Tombstone
}

All fields will be returned, but if no value has been set/ added for that field, the value will be null

server.profile.link.create({ type, profile, group, allowPublic }, cb)

Creates a message which links either a feed and profile, or group and profile.

Alternatively, if group is present, creates a link/group-profile.

Arguments:

  • type String what sort of link to make, feed-profile | group-profile
  • profile MessageId - the key for a profile (the root message of a profile tangle)
  • group GroupId (optiona) - the id for a private group you're associating with a profile. Only required in the case you're making a feed-profile type link
  • allowPublic Boolean (optional) - if you have ssb-recps-guard installed and want to bypass it for a public (unencrypted) link
  • cb Function - callback with signature (err, link) where link is the link message

Note:

  • feed-profile links are always with the feedId of the current scuttlebutt instance, so feed is not an input
  • if you link to a private profile, the link will be encrypted to the same recps as that profile

server.profile.find(opts, cb)

Arguments:

  • opts Object - an options object which currently expects properties:
    • type String - the type you created (e.g. person would find ssb message of type profile/person)
    • name String - a name that could be part of a preferredName or legalName
    • includeTombstoned Boolean (optional) - whether to include profiles which habe been tombstoned (default: false)
  • cb Function - a callback with signature (err, suggestions) where suggestions is an array of Profiles

server.profile.findByFeedId(feedId, cb)

Takes a feedId and calls back with all profiles which that feedId has linked to it. Signature of cb is cb(err, profiles) where profiles is of form:

{
  public: [Profile],
  private: [Profile]
}

NOTE:

  • profiles which have been tombstoned are not included in results
  • profiles are ordered from oldest to newest in terms of when they were linked to the feedId
  • you can call this with server.profile.findByFeedId(feedId, { getProfile }, cb), useful if you have a getter with a cache

server.profile.findByGroupId(groupId, cb)

Takes a groupId and calls back with all profiles which that feedId has linked to it. Signature of cb is cb(err, profiles) where profiles is of form:

{
  public: [Profile],
  private: [Profile]
}

NOTE:

  • profiles which have been tombstoned are not included in results
  • profiles are ordered from oldest to newest in terms of when they were linked to the feedId
  • you can call this with server.profile.findByGroupId(feedId, { getProfile }, cb), useful if you have a getter with a cache

FAQ

I want to delete my legalName, how do?

  • first, know that if you previously published a legalName it will always be part of your record (even if it's not currently displayed)
  • if you want to clear a text field, just publish an update with an empty String { legalName: {set: ''} }

How do I clear an image?

  • currently you have to over-write with another

Multiple editors for a profile?

  • this only supports one editor (the original author) at the moment
  • TODO - in future add multiple authors. This will involve adding some Access Control options to the schema

Development

Project layout (made with tree):

.
├── index.js           // ssb-server plugin (collects all methods)
├── lib                // schema-derived validators, helpers
├── method             // user facing methods
├── spec               // describes message + how to reduce them
│   ├── link
│   │   ├── feed-profile
│   │   └── group-profile
│   └── profile
│
└── test               // tests!

run npm test to run tests

Current Tags

  • 2.0.2                                ...           latest (19 days ago)

31 Versions

  • 2.0.2                                ...           19 days ago
  • 2.0.1                                ...           20 days ago
  • 2.0.0                                ...           20 days ago
  • 1.5.2                                ...           2 months ago
  • 1.5.1                                ...           3 months ago
  • 1.5.0                                ...           4 months ago
  • 1.4.0                                ...           4 months ago
  • 1.3.0                                ...           4 months ago
  • 1.2.3                                ...           4 months ago
  • 1.2.2                                ...           5 months ago
  • 1.2.1                                ...           5 months ago
  • 1.2.0                                ...           5 months ago
  • 1.1.1                                ...           5 months ago
  • 1.1.0                                ...           5 months ago
  • 1.0.2                                ...           5 months ago
  • 1.0.1                                ...           6 months ago
  • 1.0.0                                ...           6 months ago
  • 0.10.0                                ...           8 months ago
  • 0.9.0                                ...           8 months ago
  • 0.8.1                                ...           9 months ago
  • 0.8.0                                ...           10 months ago
  • 0.6.2                                ...           10 months ago
  • 0.6.1                                ...           10 months ago
  • 0.6.0                                ...           a year ago
  • 0.5.0                                ...           a year ago
  • 0.4.0                                ...           a year ago
  • 0.3.2                                ...           a year ago
  • 0.3.1                                ...           a year ago
  • 0.3.0                                ...           a year ago
  • 0.2.0                                ...           a year ago
  • 0.1.0                                ...           a year ago
Downloads
Today 0
This Week 0
This Month 25
Last Day 0
Last Week 0
Last Month 6
Dependencies (13)
Dev Dependencies (10)
Dependents (1)

Copyright 2014 - 2016 © taobao.org |