libsf

package
v0.12.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 22, 2023 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Create client

client, err := libsf.NewDefaultClient("https://notes.nas.lan")
if err != nil {
	log.Fatal(err)
}

Authenticate

email := "george.abitbol@nas.lan"
password := "12345678"

auth, err := client.GetAuthParams(email)
if err != nil {
	log.Fatal(err)
}

err = auth.IntegrityCheck()
if err != nil {
	log.Fatal(err)
}

// Create keychain containing all the keys used for encryption and authentication.
keychain := auth.SymmetricKeyPair(password)

err = client.Login(auth.Email(), keychain.Password)
if err != nil {
	log.Fatal(err)
}

Get all items

items := libsf.NewSyncItems()
items, err = client.SyncItems(items) // No sync_token and limit are setted so we get all items.
if err != nil {
	log.Fatal(err)
}

// Append `SN|ItemsKey` to the KeyChain.
for _, item := range items.Retrieved {
	if item.ContentType != libsf.ContentTypeItemsKey {
		continue
	}

	err = item.Unseal(keychain)
	if err != nil {
		log.Fatal(err)
	}
}

var last int
for i, item := range items.Retrieved {
	switch item.ContentType {
	case libsf.ContentTypeUserPreferences:
		// Unseal Preferences item using keychain.
		err = item.Unseal(keychain)
		if err != nil {
			log.Fatal(err)
		}

		// Parse metadata.
		if err = item.Note.ParseRaw(); err != nil {
			log.Fatal(err)
		}

		fmt.Println("Items are sorted by:", item.Note.GetSortingField())
	case libsf.ContentTypeNote:
		// Unseal Note item using keychain.
		err = item.Unseal(keychain)
		if err != nil {
			log.Fatal(err)
		}

		// Parse metadata.
		if err = item.Note.ParseRaw(); err != nil {
			log.Fatal(err)
		}

		fmt.Println("Title:", item.Note.Title)
		fmt.Println("Content:", item.Note.Text)

		last = i
	}
}

Update an item

item := items.Retrieved[last]
item.Note.Title += " updated"
item.Note.Text += " updated"

item.Note.SetUpdatedAtNow()
item.Note.SaveRaw()

err = item.Seal(keychain)
if err != nil {
	log.Fatal(err)
}

// Syncing updated item.
items = libsf.NewSyncItems()
items.Items = append(items.Items, item)
items, err = client.SyncItems(items)
if err != nil {
	log.Fatal(err)
}

if len(items.Conflicts) > 0 {
	log.Fatal("items conflict")
}
fmt.Println("Updated!")

Index

Constants

View Source
const (
	// ContentTypeUserPreferences for items that holds user's preferences.
	ContentTypeUserPreferences = "SN|UserPreferences"
	// ContentTypePrivileges for items that holds note's privileges.
	ContentTypePrivileges = "SN|Privileges"
	// ContentTypeComponent are items that describes an editor extension.
	ContentTypeComponent = "SN|Component"
	// ContentTypeItemsKey are items used to encrypt Note items.
	ContentTypeItemsKey = "SN|ItemsKey"
	// ContentTypeNote are the items with user's written data.
	ContentTypeNote = "Note"
)
View Source
const (
	// APIVersion20161215 allows to use the API version 20161215.
	APIVersion20161215 = "20161215"
	// APIVersion20190520 allows to use the API version 20190520.
	APIVersion20190520 = "20190520"
	// APIVersion20200115 allows to use the API version 20200115.
	APIVersion20200115 = "20200115"

	// APIVersion is the version used by default client.
	APIVersion = APIVersion20200115
)
View Source
const (
	// ProtocolVersion1 allows to use the SF protocol 001.
	ProtocolVersion1 = "001"
	// ProtocolVersion2 allows to use the SF protocol 002.
	ProtocolVersion2 = "002"
	// ProtocolVersion3 allows to use the SF protocol 003.
	ProtocolVersion3 = "003"
	// ProtocolVersion4 allows to use the SF protocol 004.
	ProtocolVersion4 = "004"
)

Variables

View Source
var (
	// ErrUnsupportedVersion is raised when user params version is lesser than `002`.
	ErrUnsupportedVersion = errors.New("libsf: unsupported version")
	// ErrLowPasswordCost occurred when cost of password is too low for the used KDF.
	ErrLowPasswordCost = errors.New("libsf: low password cost")
)

Functions

func GenerateRandomBytes

func GenerateRandomBytes(n int) ([]byte, error)

GenerateRandomBytes returns securely generated random bytes. It will return an error if the system's secure random number generator fails to function correctly, in which case the caller should not continue.

func TimeFromToken

func TimeFromToken(token string) time.Time

TimeFromToken retrieves datetime from cursor/sync token.

func TokenFromTime

func TokenFromTime(t time.Time) (token string)

TokenFromTime generates cursor/sync token for given time.

func VersionGreaterOrEqual added in v0.6.0

func VersionGreaterOrEqual(version, current string) bool

VersionGreaterOrEqual returns true if current is not empty and greater or equal to version.

func VersionLesser added in v0.6.0

func VersionLesser(version, current string) bool

VersionLesser returns true if current is empty or lesser to version.

Types

type Auth

type Auth interface {
	// Email returns the email used for authentication.
	Email() string
	// Identifier returns the identifier (email) used for authentication.
	Identifier() string
	// Version returns the encryption scheme version.
	Version() string
	// IntegrityCheck checks if the Auth params are valid.
	IntegrityCheck() error
	// SymmetricKeyPair returns a KeyChain for the given uip (plaintext password of the user).
	// https://github.com/standardfile/standardfile.github.io/blob/master/doc/spec.md#client-instructions
	SymmetricKeyPair(uip string) *KeyChain
}

An Auth holds all the params needed to create the credentials and cipher keys.

type Client

type Client interface {
	// GetAuthParams returns the parameters of a user from StandardFile server.
	GetAuthParams(email string) (Auth, error)
	// Login connects the Client to the StandardFile server.
	Login(email, password string) error
	// Logout disconnects the client (since API 20200115).
	Logout() error
	// BearerToken returns the authentication used for requests sent to the StandardFile server.
	// It can be a JWT or an access token from a session.
	BearerToken() string
	// SetBearerToken sets the authentication used for requests sent to the StandardFile server.
	// It can be a JWT or an access token from a session.
	SetBearerToken(token string)
	// Session returns the authentication session used for authentication (since API 20200115).
	Session() Session
	// SetSession sets the authentication session used for authentication (since API 20200115).
	// It also uses its access token as the bearer token.
	SetSession(session Session)
	// RefreshSession gets a new pair of tokens by refreshing the session.
	RefreshSession(access, refresh string) (*Session, error)
	// SyncItems synchronizes local items with the StandardFile server.
	SyncItems(si SyncItems) (SyncItems, error)
}

A Client defines all interactions that can be performed on a StandardFile server.

func NewClient

func NewClient(c *http.Client, apiversion string, endpoint string) (Client, error)

NewClient returns a new Client.

func NewDefaultClient

func NewDefaultClient(endpoint string) (Client, error)

NewDefaultClient returns a new Client with default HTTP client.

type ConflictItem added in v0.5.0

type ConflictItem struct {
	UnsavedItem Item   `json:"unsaved_item,omitempty"`
	ServerItem  Item   `json:"server_item,omitempty"`
	Type        string `json:"type"`
}

A ConflictItem is an object containing an item that can't be saved caused by conflicts. Used since API version 20190520.

type Item

type Item struct {
	ID        string     `json:"uuid"`
	CreatedAt *time.Time `json:"created_at"`
	UpdatedAt *time.Time `json:"updated_at"`

	UserID           string `json:"user_uuid"`
	Content          string `json:"content"`
	ContentType      string `json:"content_type"`
	ItemsKeyID       string `json:"items_key_id"` // Since 20200115
	EncryptedItemKey string `json:"enc_item_key"`
	Deleted          bool   `json:"deleted"`

	// Internal
	Version    string `json:"-"`
	AuthParams Auth   `json:"-"`
	Note       *Note  `json:"-"`
	// contains filtered or unexported fields
}

An Item holds all the data created by end user.

func (*Item) Seal

func (i *Item) Seal(keychain *KeyChain) error

Seal encrypts Note to item's Content.

func (*Item) Unseal

func (i *Item) Unseal(keychain *KeyChain) error

Unseal decrypts the item's Content into Note. `SN|ItemsKey` are append in the provided KeyChain.

type KeyChain added in v0.6.0

type KeyChain struct {
	Version   string            `json:"version"`
	Password  string            `json:"password,omitempty"` // Server's password
	MasterKey string            `json:"mk"`
	AuthKey   string            `json:"ak,omitempty"` // Before protocol 004
	ItemsKey  map[string]string `json:"-"`            // Since protocol 004
}

A KeyChain contains all the keys used for encryption and authentication.

func (*KeyChain) GenerateItemEncryptionKey added in v0.6.0

func (k *KeyChain) GenerateItemEncryptionKey() (string, error)

GenerateItemEncryptionKey generates a key used to encrypt item's content. ProtocolVersion3 is a 512 length bytes key that will be split in half, each being 256 bits. ProtocolVersion4 is a 32 length bytes key that be used as is.

type Note

type Note struct {
	Title        string          `json:"title"`
	Text         string          `json:"text"`
	PreviewPlain string          `json:"preview_plain"`
	PreviewHTML  string          `json:"preview_html"`
	References   json.RawMessage `json:"references"` // unstructured data
	AppData      json.RawMessage `json:"appData"`    // unstructured data
	// contains filtered or unexported fields
}

A Note is plaintext Item content.

func (*Note) GetSortingField

func (n *Note) GetSortingField() string

GetSortingField returns the field on which all notes are sorted. Only for `SN|UserPreferences` items, it returns an empty string if nothing found.

func (*Note) ParseRaw

func (n *Note) ParseRaw() error

ParseRaw parses unstructured raw fields. Needed before using other methods on Note object.

func (*Note) SaveRaw

func (n *Note) SaveRaw()

SaveRaw persists the unstructured fields to raw data.

func (*Note) SetUpdatedAtNow

func (n *Note) SetUpdatedAtNow()

SetUpdatedAtNow sets current time as last update time.

func (*Note) UpdatedAt

func (n *Note) UpdatedAt() time.Time

UpdatedAt returns the last update time of the note. If not found or error, "zero" time is returned.

type SFError

type SFError struct {
	StatusCode int
	Err        struct {
		Message string `json:"message"`
	} `json:"error"`
}

An SFError reprensents an HTTP error returned by StandardFile server.

func (*SFError) Error

func (e *SFError) Error() string

type Session added in v0.6.0

type Session struct {
	AccessToken       string    `json:"access_token"`
	RefreshToken      string    `json:"refresh_token"`
	AccessExpiration  time.Time `json:"access_expiration"`
	RefreshExpiration time.Time `json:"refresh_expiration"`
}

A Session contains details about a session.

func (Session) AccessExpired added in v0.6.0

func (s Session) AccessExpired() bool

AccessExpired returns true if the access token is expired.

func (Session) AccessExpiredAt added in v0.6.0

func (s Session) AccessExpiredAt(t time.Time) bool

AccessExpiredAt returns true if the access token is expired at the given time.

func (Session) Defined added in v0.6.0

func (s Session) Defined() bool

Defined returns true if session's fields are defined.

func (Session) MarshalJSON added in v0.6.4

func (s Session) MarshalJSON() ([]byte, error)

func (Session) RefreshExpired added in v0.6.0

func (s Session) RefreshExpired() bool

RefreshExpired returns true if the refresh token is expired.

func (*Session) UnmarshalJSON added in v0.6.3

func (s *Session) UnmarshalJSON(data []byte) error

type SyncItems

type SyncItems struct {
	// Common fields
	API              string `json:"api"` // Since 20190520
	ComputeIntegrity bool   `json:"compute_integrity,omitempty"`
	Limit            int    `json:"limit,omitempty"`
	SyncToken        string `json:"sync_token,omitempty"`
	CursorToken      string `json:"cursor_token,omitempty"`
	ContentType      string `json:"content_type,omitempty"` // optional, only return items of these type if present

	// Fields used for request
	Items []*Item `json:"items,omitempty"`

	// Fields used in response
	Retrieved []*Item `json:"retrieved_items,omitempty"`
	Saved     []*Item `json:"saved_items,omitempty"`

	Unsaved   []*UnsavedItem  `json:"unsaved,omitempty"`   // Before 20190520 (Since 20161215 at least)
	Conflicts []*ConflictItem `json:"conflicts,omitempty"` // Since 20190520
}

A SyncItems is used when a client want to sync items.

func NewSyncItems

func NewSyncItems() SyncItems

NewSyncItems returns an empty SyncItems with initilized defaults.

type UnsavedItem

type UnsavedItem struct {
	Item  Item `json:"item"`
	Error struct {
		Message string `json:"message"`
		Tag     string `json:"tag"`
	} `json:"error"`
}

An UnsavedItem is an object containing an item that has not been saved. Used before API version 20190520.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL