diff --git a/.gitignore b/.gitignore
index 1a6512d14ef..debd4d061c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
/assets/locales/*.po
!/assets/locales/en.po
/cozy-stack*
+/scripts/cozy-stack*
/debian
/storage
/tests/clone/generated
diff --git a/assets/.externals b/assets/.externals
index e8e8e00af31..05b55b4775a 100644
--- a/assets/.externals
+++ b/assets/.externals
@@ -11,20 +11,20 @@
#
name ./js/cozy-client.min.js
-url https://raw.githubusercontent.com/cozy/cozy-client-js/v0.12.1/dist/cozy-client.min.js
-sha256 2c8fab17148a133a6ff3ad61445ef12f62cd9be6f392a0801f822d021a72e52d
+url https://raw.githubusercontent.com/cozy/cozy-client-js/v0.13.0/dist/cozy-client.min.js
+sha256 adff3cdbe79c01f6d6b046fd4494e8d37669ccff442f6ab8ae2f6ed8a83241bf
name ./js/cozy-client.min.js.map
-url https://raw.githubusercontent.com/cozy/cozy-client-js/v0.12.1/dist/cozy-client.min.js.map
+url https://raw.githubusercontent.com/cozy/cozy-client-js/v0.13.0/dist/cozy-client.min.js.map
sha256 290d9610010534cdc8454424825b29913303579b6ab63181100f84713439c0a5
name ./js/cozy-bar.min.js
-url https://unpkg.com/cozy-bar@6.1.1/dist/cozy-bar.min.js
-sha256 d18d72e55f24859be88cd76733d46ad7a9e906a26d930ca1db4242c9a3697616
+url https://unpkg.com/cozy-bar@5.4.0/dist/cozy-bar.min.js
+sha256 ea0638d11a6256f5821f725a3b95535fed0354090c34355b61445d0643b3fb30
name ./css/cozy-bar.min.css
-url https://unpkg.com/cozy-bar@6.1.1/dist/cozy-bar.min.css
-sha256 c844880a4dd5a16af92b33db416ee736c0ea1d3d214f8d1d171981aab7d58e20
+url https://unpkg.com/cozy-bar@5.4.0/dist/cozy-bar.min.css
+sha256 3948f637b56cca2a0eeaccd7e3ed8ce476ba3161465f697f4a2a7f8665248e92
name ./js/piwik.js
url https://piwik.cozycloud.cc/piwik.js
diff --git a/assets/images/icon-konnectors-result.svg b/assets/images/icon-konnectors-result.svg
deleted file mode 100644
index 409058e164b..00000000000
--- a/assets/images/icon-konnectors-result.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/assets/locales/en.po b/assets/locales/en.po
index e22dca5aa42..90d3adc2129 100644
--- a/assets/locales/en.po
+++ b/assets/locales/en.po
@@ -49,7 +49,7 @@ msgid "Login Password button hide"
msgstr "hide"
msgid "Login Long Session"
-msgstr "Memorize"
+msgstr "Remember me"
msgid "Login Submit"
msgstr "Log in"
@@ -218,6 +218,15 @@ msgstr "Address of this Cozy does not exist"
msgid "Error Instance not found Message"
msgstr "You may have entered a wrong address form a typing mistake. To make sure, please check the address of your Cozy sent to you by e-mail during its creation."
+msgid "Error Application not found Title"
+msgstr "Application not yet available"
+
+msgid "Error Application not found Message"
+msgstr "We are sorry. This application is not yet available in your Cozy."
+
+msgid "Error Application not found Action"
+msgstr "Go to your home"
+
msgid "Error Contact us"
msgstr "A problem, a question ? Contact us at"
@@ -400,15 +409,6 @@ msgstr ""
"You never asked for a new password? In this case you can forget this email.\n"
"Just so you know, you have 15 minutes to choose a new password, then this email will self-destruct."
-msgid "Mail Konnector Error Subject"
-msgstr "Collection problem for your Cozy"
-
-msgid "Mail Konnector Error Intro"
-msgstr ""
-"Something wrong happened when we tried to gather the data from your {{.KonnectorName}} account.\n"
-"If you want more information, please go to the configuration page {{.KonnectorPage}} of your account.\n"
-"If the problem remains, please contact us at contact@cozycloud.cc\n"
-
msgid "Mail Archive Subject"
msgstr "Archive of your Cozy data"
@@ -552,18 +552,24 @@ msgid "Sharing Online help"
msgstr "Try out online help."
msgid "Notifications Disk Quota Subject"
-msgstr "You have reached 90% of your available storage"
+msgstr "You have currently reached 90% of your Cozy space."
msgid "Notifications Disk Quota Intro"
-msgstr ""
-"You have reached 90% of your available storage. When reach your storage quota, you will not be able to add any more files to your Cozy.\"
-"In order to keep your account below its storage quota, you can delete files from your Cozy or subscribe to a new option."
+msgstr "You have two options to get more space."
+
+msgid "Notifications Disk Quota offers instruction"
+msgstr "Option 1: Upgrade your account\n"
+"Upgrade your Cozy by choosing new offer to get lots more space"
+
+msgid "Notifications Disk Quota offers text"
+msgstr "Upgrade now"
-msgid "Notifications Disk Quota instruction"
-msgstr "Click on this button to subscribe to a new option and get more data in your Cozy."
+msgid "Notifications Disk Quota free instructions"
+msgstr "Option 2: Free up space\n"
+"Save space by deleting unneeded files"
-msgid "Notifications Disk Quota text"
-msgstr "Subscribe for more data"
+msgid "Notifications Disk Quota free text"
+msgstr "Free up storage space"
msgid "Terms of services have been updated"
msgstr "To comply with the GDPR, Cozy Cloud has updated its Terms of Services that have taken effect on May 25, 2018"
diff --git a/assets/styles/stack.css b/assets/styles/stack.css
index e8f130ce11c..4f3823a921c 100644
--- a/assets/styles/stack.css
+++ b/assets/styles/stack.css
@@ -243,9 +243,6 @@ li[class^="io.cozy.files"]:before {
li[class^="io.cozy.konnectors"]:before {
background-image: url('../images/icon-konnectors.svg');
}
-li[class^="io.cozy.konnectors.result"]:before {
- background-image: url('../images/icon-konnectors-result.svg');
-}
li[class^="io.cozy.notifications"]:before {
background-image: url('../images/icon-notifications.svg');
}
diff --git a/assets/templates/error.html b/assets/templates/error.html
index 53391b7f30f..dbc4df90db0 100644
--- a/assets/templates/error.html
+++ b/assets/templates/error.html
@@ -27,6 +27,9 @@
{{if .ErrorTitle}}{{t .ErrorTitle}}{{else}}{{t "Error Title"}}{{end}}
{{$p}}
{{end}}
{{end}}
+ {{if .ActionURL }}
+ {{t .ActionTitle}}
+ {{end}}
{{t "Error Contact us" }} contact@cozycloud.cc .
diff --git a/client/instances.go b/client/instances.go
index 5a4780243d8..290b369151b 100644
--- a/client/instances.go
+++ b/client/instances.go
@@ -77,10 +77,11 @@ type TokenOptions struct {
// OAuthClientOptions is a struct holding all the options to generate an OAuth
// client associated to an instance.
type OAuthClientOptions struct {
- Domain string
- RedirectURI string
- ClientName string
- SoftwareID string
+ Domain string
+ RedirectURI string
+ ClientName string
+ SoftwareID string
+ AllowLoginScope bool
}
// UpdatesOptions is a struct holding all the options to launch an update.
@@ -219,29 +220,6 @@ func (c *Client) DestroyInstance(domain string) error {
return err
}
-// FsckInstance returns the list of the inconsistencies in the VFS.
-func (c *Client) FsckInstance(domain string, prune, dryRun bool) ([]map[string]string, error) {
- if !validDomain(domain) {
- return nil, fmt.Errorf("Invalid domain: %s", domain)
- }
- res, err := c.Req(&request.Options{
- Method: "GET",
- Path: "/instances/" + url.PathEscape(domain) + "/fsck",
- Queries: url.Values{
- "Prune": {strconv.FormatBool(prune)},
- "DryRun": {strconv.FormatBool(dryRun)},
- },
- })
- if err != nil {
- return nil, err
- }
- var list []map[string]string
- if err = json.NewDecoder(res.Body).Decode(&list); err != nil {
- return nil, err
- }
- return list, nil
-}
-
// GetToken is used to generate a toke with the specified options.
func (c *Client) GetToken(opts *TokenOptions) (string, error) {
q := url.Values{
@@ -273,10 +251,11 @@ func (c *Client) GetToken(opts *TokenOptions) (string, error) {
// instance.
func (c *Client) RegisterOAuthClient(opts *OAuthClientOptions) (map[string]interface{}, error) {
q := url.Values{
- "Domain": {opts.Domain},
- "RedirectURI": {opts.RedirectURI},
- "ClientName": {opts.ClientName},
- "SoftwareID": {opts.SoftwareID},
+ "Domain": {opts.Domain},
+ "RedirectURI": {opts.RedirectURI},
+ "ClientName": {opts.ClientName},
+ "SoftwareID": {opts.SoftwareID},
+ "AllowLoginScope": {strconv.FormatBool(opts.AllowLoginScope)},
}
res, err := c.Req(&request.Options{
Method: "POST",
diff --git a/client/tlsclient/tlsclient.go b/client/tlsclient/tlsclient.go
new file mode 100644
index 00000000000..3c5a153270a
--- /dev/null
+++ b/client/tlsclient/tlsclient.go
@@ -0,0 +1,290 @@
+package tlsclient
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/hex"
+ "encoding/pem"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "strconv"
+ "time"
+
+ "github.com/cozy/cozy-stack/pkg/utils"
+)
+
+type HTTPEndpoint struct {
+ Host string
+ Port int
+ Timeout time.Duration
+ EnvPrefix string
+
+ RootCAFile string
+ ClientCertificateFiles ClientCertificateFilePair
+ PinnedKey string
+ InsecureSkipValidation bool
+}
+
+type ClientCertificateFilePair struct {
+ KeyFile string
+ CertificateFile string
+}
+
+type tlsConfig struct {
+ clientCertificates []tls.Certificate
+ rootCAs []*x509.Certificate
+ pinnedKeys [][]byte
+ skipVerification bool
+}
+
+func generateURL(host string, port int) (*url.URL, error) {
+ u, err := url.Parse(host)
+ if err != nil {
+ return nil, err
+ }
+ if u.Scheme == "" {
+ u = &url.URL{
+ Scheme: "http",
+ Host: net.JoinHostPort(host, strconv.Itoa(port)),
+ }
+ }
+ return u, nil
+}
+
+func NewHTTPClient(opt HTTPEndpoint) (client *http.Client, u *url.URL, err error) {
+ if opt.Host != "" || opt.Port > 0 {
+ u, err = generateURL(opt.Host, opt.Port)
+ if err != nil {
+ return
+ }
+ }
+ c := &tlsConfig{}
+ if u != nil {
+ c, u, err = fromURL(c, u)
+ if err != nil {
+ return
+ }
+ }
+ if opt.EnvPrefix != "" {
+ c, err = fromEnv(c, opt.EnvPrefix)
+ if err != nil {
+ return
+ }
+ }
+ if opt.RootCAFile != "" {
+ if err = c.LoadRootCAFile(opt.RootCAFile); err != nil {
+ return
+ }
+ }
+ if opt.ClientCertificateFiles.CertificateFile != "" {
+ if err = c.LoadClientCertificateFile(
+ opt.ClientCertificateFiles.CertificateFile,
+ opt.ClientCertificateFiles.KeyFile,
+ ); err != nil {
+ return
+ }
+ }
+ if opt.PinnedKey != "" {
+ if err = c.AddHexPinnedKey(opt.PinnedKey); err != nil {
+ return
+ }
+ }
+ if opt.InsecureSkipValidation {
+ c.SetInsecureSkipValidation()
+ }
+ client = &http.Client{
+ Timeout: opt.Timeout,
+ Transport: &http.Transport{TLSClientConfig: c.Config()},
+ }
+ return
+}
+
+func fromURL(c *tlsConfig, u *url.URL) (conf *tlsConfig, uCopy *url.URL, err error) {
+ uCopy = utils.CloneURL(u)
+ q := uCopy.Query()
+ if u.Scheme == "https" {
+ if rootCAFile := q.Get("ca"); rootCAFile != "" {
+ if err = c.LoadRootCAFile(rootCAFile); err != nil {
+ return
+ }
+ }
+ if certFile := q.Get("cert"); certFile != "" {
+ if keyFile := q.Get("key"); keyFile != "" {
+ if err = c.LoadClientCertificateFile(certFile, keyFile); err != nil {
+ return
+ }
+ }
+ }
+ if hexPinnedKey := q.Get("fp"); hexPinnedKey != "" {
+ if err = c.AddHexPinnedKey(hexPinnedKey); err != nil {
+ return
+ }
+ }
+ if t := q.Get("validate"); t == "0" || t == "false" || t == "FALSE" {
+ c.SetInsecureSkipValidation()
+ }
+ }
+ q.Del("ca")
+ q.Del("cert")
+ q.Del("key")
+ q.Del("fp")
+ q.Del("validate")
+ uCopy.RawQuery = q.Encode()
+ return c, uCopy, nil
+}
+
+func fromEnv(c *tlsConfig, envPrefix string) (conf *tlsConfig, err error) {
+ if rootCAFile := os.Getenv(envPrefix + "_CA"); rootCAFile != "" {
+ if err = c.LoadRootCAFile(rootCAFile); err != nil {
+ return
+ }
+ }
+ if certFile := os.Getenv(envPrefix + "_CERT"); certFile != "" {
+ if keyFile := os.Getenv(envPrefix + "_KEY"); keyFile != "" {
+ if err = c.LoadClientCertificateFile(certFile, keyFile); err != nil {
+ return
+ }
+ }
+ }
+ if hexPinnedKey := os.Getenv(envPrefix + "_FINGERPRINT"); hexPinnedKey != "" {
+ if err = c.AddHexPinnedKey(hexPinnedKey); err != nil {
+ return
+ }
+ }
+ if t := os.Getenv(envPrefix + "_VALIDATE"); t == "0" || t == "false" || t == "FALSE" {
+ c.SetInsecureSkipValidation()
+ }
+ return c, nil
+}
+
+func (s *tlsConfig) LoadClientCertificateFile(certFile, keyFile string) error {
+ cert, err := tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return fmt.Errorf("tlsclient: could not load client certificate file: %s", err)
+ }
+ s.clientCertificates = append(s.clientCertificates, cert)
+ return nil
+}
+
+func (s *tlsConfig) LoadClientCertificate(certPEMBlock, keyPEMBlock []byte) error {
+ cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock)
+ if err != nil {
+ return fmt.Errorf("tlsclient: could not load client certificate file: %s", err)
+ }
+ s.clientCertificates = append(s.clientCertificates, cert)
+ return nil
+}
+
+func (s *tlsConfig) LoadRootCA(rootCA []byte) error {
+ cert, err := x509.ParseCertificate(rootCA)
+ if err != nil {
+ return err
+ }
+ s.rootCAs = append(s.rootCAs, cert)
+ return nil
+}
+
+func (s *tlsConfig) LoadRootCAFile(rootCAFile string) error {
+ pemCerts, err := ioutil.ReadFile(rootCAFile)
+ if err != nil {
+ return fmt.Errorf("tlsclient: could not load root CA file %q: %s", rootCAFile, err)
+ }
+ ok := false
+ for len(pemCerts) > 0 {
+ var block *pem.Block
+ block, pemCerts = pem.Decode(pemCerts)
+ if block == nil {
+ break
+ }
+ if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+ continue
+ }
+ if err = s.LoadRootCA(block.Bytes); err != nil {
+ continue
+ }
+ ok = true
+ }
+ if !ok {
+ return fmt.Errorf("tlsclient: could not load any certificate from the given ROOTCA file: %q", rootCAFile)
+ }
+ return nil
+}
+
+func (s *tlsConfig) SetInsecureSkipValidation() {
+ s.skipVerification = true
+}
+
+func (s *tlsConfig) AddHexPinnedKey(hexPinnedKey string) error {
+ pinnedKey, err := hex.DecodeString(hexPinnedKey)
+ if err != nil {
+ return fmt.Errorf("tlsclient: invalid hexadecimal fingerprint: %s", err)
+ }
+ expected := sha256.Size
+ given := len(pinnedKey)
+ if given != expected {
+ return fmt.Errorf("tlsclient: invalid fingerprint size for %s, expected %d got %d", hexPinnedKey,
+ expected, given)
+ }
+ s.pinnedKeys = append(s.pinnedKeys, pinnedKey)
+ return nil
+}
+
+func (s *tlsConfig) Config() *tls.Config {
+ conf := &tls.Config{}
+ conf.InsecureSkipVerify = s.skipVerification
+
+ if len(s.rootCAs) > 0 {
+ rootCAs := x509.NewCertPool()
+ for _, cert := range s.rootCAs {
+ rootCAs.AddCert(cert)
+ }
+ conf.RootCAs = rootCAs
+ }
+
+ if len(s.clientCertificates) > 0 {
+ conf.Certificates = make([]tls.Certificate, len(s.clientCertificates))
+ copy(conf.Certificates, s.clientCertificates)
+ }
+
+ if len(s.pinnedKeys) > 0 {
+ conf.VerifyPeerCertificate = verifyCertificatePinnedKey(s.pinnedKeys)
+ }
+ return conf
+}
+
+func verifyCertificatePinnedKey(pinnedKeys [][]byte) func(certs [][]byte, verifiedChains [][]*x509.Certificate) error {
+ return func(certs [][]byte, verifiedChains [][]*x509.Certificate) error {
+ // Check for leaf pinning first
+ for _, asn1 := range certs {
+ cert, err := x509.ParseCertificate(asn1)
+ if err != nil {
+ return err
+ }
+ fingerPrint := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
+ for _, pinnedKey := range pinnedKeys {
+ if bytes.Equal(pinnedKey, fingerPrint[:]) {
+ return nil
+ }
+ }
+ }
+ // Then check for intermediate pinning
+ for _, verifiedChain := range verifiedChains {
+ if len(verifiedChain) > 0 {
+ verifiedCert := verifiedChain[0]
+ fingerPrint := sha256.Sum256(verifiedCert.RawSubjectPublicKeyInfo)
+ for _, pinnedKey := range pinnedKeys {
+ if bytes.Equal(pinnedKey, fingerPrint[:]) {
+ return nil
+ }
+ }
+ }
+ }
+ return fmt.Errorf("tlsclient: could not find the valid pinned key from proposed ones")
+ }
+}
diff --git a/cmd/config.go b/cmd/config.go
index b486845b422..6b3510d6a3e 100644
--- a/cmd/config.go
+++ b/cmd/config.go
@@ -11,15 +11,22 @@ import (
"path"
"path/filepath"
+ "github.com/cozy/cozy-stack/client/request"
"github.com/cozy/cozy-stack/pkg/accounts"
"github.com/cozy/cozy-stack/pkg/config"
"github.com/cozy/cozy-stack/pkg/crypto"
"github.com/cozy/cozy-stack/pkg/keymgmt"
+ "github.com/cozy/cozy-stack/pkg/statik/fs"
"github.com/cozy/cozy-stack/pkg/utils"
"github.com/howeyc/gopass"
"github.com/spf13/cobra"
)
+var flagURL string
+var flagName string
+var flagShasum string
+var flagContext string
+
var configCmdGroup = &cobra.Command{
Use: "config ",
Short: "Show and manage configuration elements",
@@ -133,9 +140,9 @@ specified path.
The decryptor key filename is given the ".dec" extension suffix.
The encryptor key filename is given the ".enc" extension suffix.
-The files permissions are 0400.
+The files permissions are 0400.`,
-example: cozy-stack config gen-keys ~/credentials-key
+ Example: `$ cozy-stack config gen-keys ~/credentials-key
keyfiles written in:
~/credentials-key.enc
~/credentials-key.dec
@@ -150,9 +157,11 @@ keyfiles written in:
decryptorFilename := filename + ".dec"
marshaledEncryptorKey, marshaledDecryptorKey, err := keymgmt.GenerateEncodedNACLKeyPair()
+
if err != nil {
return nil
}
+
if err = writeFile(encryptorFilename, marshaledEncryptorKey, 0400); err != nil {
return err
}
@@ -164,6 +173,92 @@ keyfiles written in:
},
}
+var encryptCredentialsDataCmd = &cobra.Command{
+ Use: "encrypt-data ",
+ Short: "Encrypt data with the specified encryption keyfile.",
+ Long: `cozy-stack config encrypt-data encrypts any valid JSON data`,
+ Example: `
+$ ./cozy-stack config encrypt-data ~/.cozy/key.enc "{\"foo\": \"bar\"}"
+$ bmFjbNFjY+XZkS26YtVPUIKKm/JdnAGwG30n6A4ypS1p1dHev8hOtaRbW+lGneoO7PS9JCW8U5GSXhASu+c3UkaZ
+`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 2 {
+ return cmd.Usage()
+ }
+
+ // Check if we have good-formatted JSON
+ var result map[string]interface{}
+ err := json.Unmarshal([]byte(args[1]), &result)
+ if err != nil {
+ return err
+ }
+
+ encKeyStruct, err := readKeyFromFile(args[0])
+ if err != nil {
+ return err
+ }
+ dataEncrypted, err := accounts.EncryptBufferWithKey(encKeyStruct, []byte(args[1]))
+ if err != nil {
+ return err
+ }
+ data := base64.StdEncoding.EncodeToString(dataEncrypted)
+ fmt.Printf("%s\n", data)
+
+ return nil
+ },
+}
+
+var decryptCredentialsDataCmd = &cobra.Command{
+ Use: "decrypt-data ",
+ Short: "Decrypt data with the specified decryption keyfile.",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 2 {
+ return cmd.Usage()
+ }
+
+ decKeyStruct, err := readKeyFromFile(args[0])
+ if err != nil {
+ return err
+ }
+
+ dataEncrypted, err := base64.StdEncoding.DecodeString(args[1])
+ if err != nil {
+ return err
+ }
+ decrypted, err := accounts.DecryptBufferWithKey(decKeyStruct, dataEncrypted)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("%s\n", decrypted)
+
+ return nil
+ },
+}
+
+var encryptCredentialsCmd = &cobra.Command{
+ Use: "encrypt-creds ",
+ Aliases: []string{"encrypt-credentials"},
+ Short: "Encrypt the given credentials with the specified decryption keyfile.",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 3 {
+ return cmd.Usage()
+ }
+
+ credsEncryptor, err := readKeyFromFile(args[0])
+ if err != nil {
+ return err
+ }
+
+ encryptedCreds, err := accounts.EncryptCredentialsWithKey(credsEncryptor, args[1], args[2])
+ if err != nil {
+ return err
+ }
+ fmt.Printf("Encrypted credentials: %s\n", encryptedCreds)
+ return nil
+ },
+}
+
var decryptCredentialsCmd = &cobra.Command{
Use: "decrypt-creds ",
Aliases: []string{"decrypt-credentials"},
@@ -173,11 +268,7 @@ var decryptCredentialsCmd = &cobra.Command{
return cmd.Usage()
}
- keyBytes, err := ioutil.ReadFile(args[0])
- if err != nil {
- return err
- }
- credsDecryptor, err := keymgmt.UnmarshalNACLKey(keyBytes)
+ credsDecryptor, err := readKeyFromFile(args[0])
if err != nil {
return err
}
@@ -215,10 +306,101 @@ func writeFile(filename string, data []byte, perm os.FileMode) error {
return err
}
+func readKeyFromFile(filepath string) (*keymgmt.NACLKey, error) {
+ keyBytes, err := ioutil.ReadFile(filepath)
+ if err != nil {
+ return nil, err
+ }
+
+ return keymgmt.UnmarshalNACLKey(keyBytes)
+}
+
+var insertAssetCmd = &cobra.Command{
+ Use: "insert-asset --url --name --shasum --context ",
+ Short: "Inserts an asset",
+ Long: "Inserts a custom asset in a specific context",
+ Example: "$ cozy-stack config insert-asset --url file:///foo/bar/baz.js --name /foo/bar/baz.js --shasum 0763d6c2cebee0880eb3a9cc25d38cd23db39b5c3802f2dc379e408c877a2788 --context foocontext",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ // Check params
+ var customAssets []fs.AssetOption
+
+ assetOption := fs.AssetOption{
+ URL: flagURL,
+ Name: flagName,
+ Shasum: flagShasum,
+ Context: flagContext,
+ }
+
+ customAssets = append(customAssets, assetOption)
+
+ marshaledAssets, err := json.Marshal(customAssets)
+ if err != nil {
+ return err
+ }
+
+ c := newAdminClient()
+ req := &request.Options{
+ Method: "POST",
+ Path: "instances/assets",
+ Body: bytes.NewReader(marshaledAssets),
+ }
+ res, err := c.Req(req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+ return nil
+ },
+}
+
+var listAssetCmd = &cobra.Command{
+ Use: "ls-assets",
+ Short: "List assets",
+ Long: "List assets currently served by the stack",
+ Example: "$ cozy-stack config ls-assets",
+ RunE: func(cmd *cobra.Command, args []string) error {
+
+ c := newAdminClient()
+ req := &request.Options{
+ Method: "GET",
+ Path: "instances/assets",
+ }
+ res, err := c.Req(req)
+ if err != nil {
+ return err
+ }
+ defer res.Body.Close()
+
+ var v interface{}
+
+ err = json.NewDecoder(res.Body).Decode(&v)
+ if err != nil {
+ return err
+ }
+
+ json, err := json.MarshalIndent(v, "", " ")
+ if err != nil {
+ return err
+ }
+
+ fmt.Println(string(json))
+ return nil
+ },
+}
+
func init() {
configCmdGroup.AddCommand(configPrintCmd)
configCmdGroup.AddCommand(adminPasswdCmd)
configCmdGroup.AddCommand(genKeysCmd)
+ configCmdGroup.AddCommand(encryptCredentialsDataCmd)
+ configCmdGroup.AddCommand(decryptCredentialsDataCmd)
+ configCmdGroup.AddCommand(encryptCredentialsCmd)
configCmdGroup.AddCommand(decryptCredentialsCmd)
+ configCmdGroup.AddCommand(insertAssetCmd)
+ configCmdGroup.AddCommand(listAssetCmd)
RootCmd.AddCommand(configCmdGroup)
+ insertAssetCmd.Flags().StringVar(&flagURL, "url", "", "The URL of the asset")
+ insertAssetCmd.Flags().StringVar(&flagName, "name", "", "The name of the asset")
+ insertAssetCmd.Flags().StringVar(&flagShasum, "shasum", "", "The shasum of the asset")
+ insertAssetCmd.Flags().StringVar(&flagContext, "context", "", "The context of the asset")
}
diff --git a/cmd/fixer.go b/cmd/fixer.go
index 9f4c8ed155e..bc582ad01e4 100644
--- a/cmd/fixer.go
+++ b/cmd/fixer.go
@@ -12,7 +12,6 @@ import (
"net/url"
"os"
"regexp"
- "strconv"
"strings"
"github.com/cozy/cozy-stack/pkg/contacts"
@@ -250,43 +249,6 @@ var redisFixer = &cobra.Command{
},
}
-var orphanAccountsFixer = &cobra.Command{
- Use: "accounts-orphans ",
- Aliases: []string{"account-orphans"},
- Short: "Rebuild triggers associated with orphan accounts",
- RunE: func(cmd *cobra.Command, args []string) error {
- if len(args) != 1 {
- return cmd.Usage()
- }
- domain := args[0]
- c := newAdminClient()
- res, err := c.Req(&request.Options{
- Method: "POST",
- Path: fmt.Sprintf("/instances/%s/orphan_accounts", url.PathEscape(domain)),
- Queries: url.Values{
- "DryRun": {strconv.FormatBool(dryRunFlag)},
- },
- })
- if err != nil {
- return err
- }
- var data []json.RawMessage
- if err = request.ReadJSON(res.Body, &data); err != nil {
- return err
- }
- b, err := json.MarshalIndent(data, "", " ")
- if err != nil {
- return err
- }
- if len(data) == 0 {
- fmt.Println("Nothing to do")
- } else {
- fmt.Println(string(b))
- }
- return nil
- },
-}
-
var thumbnailsFixer = &cobra.Command{
Use: "thumbnails ",
Short: "Rebuild thumbnails image for images files",
@@ -443,7 +405,6 @@ var contactEmailsFixer = &cobra.Command{
}
func init() {
- orphanAccountsFixer.Flags().BoolVar(&dryRunFlag, "dry-run", false, "Dry run")
thumbnailsFixer.Flags().BoolVar(&dryRunFlag, "dry-run", false, "Dry run")
thumbnailsFixer.Flags().BoolVar(&withMetadataFlag, "with-metadata", false, "Recalculate images metadata")
@@ -454,7 +415,6 @@ func init() {
fixerCmdGroup.AddCommand(mimeFixerCmd)
fixerCmdGroup.AddCommand(onboardingsFixer)
fixerCmdGroup.AddCommand(redisFixer)
- fixerCmdGroup.AddCommand(orphanAccountsFixer)
fixerCmdGroup.AddCommand(thumbnailsFixer)
fixerCmdGroup.AddCommand(contactEmailsFixer)
diff --git a/cmd/instances.go b/cmd/instances.go
index e4cf3b46cef..6e3eb4415c3 100644
--- a/cmd/instances.go
+++ b/cmd/instances.go
@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "net/url"
"os"
"strconv"
"strings"
@@ -13,6 +14,7 @@ import (
"time"
"github.com/cozy/cozy-stack/client"
+ "github.com/cozy/cozy-stack/client/request"
"github.com/cozy/cozy-stack/pkg/consts"
"github.com/cozy/cozy-stack/pkg/instance"
humanize "github.com/dustin/go-humanize"
@@ -33,8 +35,6 @@ var flagBlocked bool
var flagDev bool
var flagPassphrase string
var flagForce bool
-var flagFsckDry bool
-var flagFsckPrune bool
var flagJSON bool
var flagDirectory string
var flagIncreaseQuota bool
@@ -48,6 +48,8 @@ var flagTOSLatest string
var flagContextName string
var flagOnboardingFinished bool
var flagExpire time.Duration
+var flagAllowLoginScope bool
+var flagFsckIndexIntegrity bool
// instanceCmdGroup represents the instances command
var instanceCmdGroup = &cobra.Command{
@@ -494,25 +496,28 @@ in swift/localfs but not couchdb.
domain := args[0]
c := newAdminClient()
- list, err := c.FsckInstance(domain, flagFsckPrune, flagFsckDry)
+ res, err := c.Req(&request.Options{
+ Method: "GET",
+ Path: "/instances/" + url.PathEscape(domain) + "/fsck",
+ Queries: url.Values{
+ "IndexIntegrity": {strconv.FormatBool(flagFsckIndexIntegrity)},
+ },
+ })
if err != nil {
return err
}
- if len(list) == 0 {
- fmt.Printf("Instance for domain %s is clean\n", domain)
- } else {
- for _, entry := range list {
- fmt.Printf("- %q: %s\n", entry["filename"], entry["message"])
- if pruneAction := entry["prune_action"]; pruneAction != "" {
- fmt.Printf(" %s...", pruneAction)
- if pruneError := entry["prune_error"]; pruneError != "" {
- fmt.Printf("error: %s\n", pruneError)
- } else {
- fmt.Println("ok")
- }
- }
+ hasError := false
+ scanner := bufio.NewScanner(res.Body)
+ for scanner.Scan() {
+ if err = scanner.Err(); err != nil {
+ return err
}
+ fmt.Println(string(scanner.Bytes()))
+ }
+
+ if hasError {
+ os.Exit(1)
}
return nil
},
@@ -628,10 +633,11 @@ var oauthClientInstanceCmd = &cobra.Command{
}
c := newAdminClient()
oauthClient, err := c.RegisterOAuthClient(&client.OAuthClientOptions{
- Domain: args[0],
- RedirectURI: args[1],
- ClientName: args[2],
- SoftwareID: args[3],
+ Domain: args[0],
+ RedirectURI: args[1],
+ ClientName: args[2],
+ SoftwareID: args[3],
+ AllowLoginScope: flagAllowLoginScope,
})
if err != nil {
return err
@@ -647,6 +653,45 @@ var oauthClientInstanceCmd = &cobra.Command{
},
}
+var findOauthClientCmd = &cobra.Command{
+ Use: "find-oauth-client ",
+ Short: "Find an OAuth client",
+ Long: `Search an OAuth client from its SoftwareID`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) < 1 {
+ return cmd.Usage()
+ }
+ var v interface{}
+ c := newAdminClient()
+
+ q := url.Values{
+ "domain": {args[0]},
+ "software_id": {args[1]},
+ }
+
+ req := &request.Options{
+ Method: "GET",
+ Path: "instances/oauth_client",
+ Queries: q,
+ }
+ res, err := c.Req(req)
+ if err != nil {
+ return err
+ }
+ errd := json.NewDecoder(res.Body).Decode(&v)
+ if err != nil {
+ return errd
+ }
+ json, err := json.MarshalIndent(v, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(json))
+
+ return err
+ },
+}
+
var updateCmd = &cobra.Command{
Use: "update [slugs...]",
Short: "Start the updates for the specified domain instance.",
@@ -715,6 +760,40 @@ var importCmd = &cobra.Command{
},
}
+var showSwiftPrefixInstanceCmd = &cobra.Command{
+ Use: "show-swift-prefix ",
+ Short: "Show the instance swift prefix of the specified domain",
+ Example: "$ cozy-stack instances show-swift-prefix cozy.tools:8080",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ var v map[string]string
+
+ c := newAdminClient()
+ if len(args) < 1 {
+ return errors.New("The domain is missing")
+ }
+
+ req := &request.Options{
+ Method: "GET",
+ Path: "instances/" + args[0] + "/swift-prefix",
+ }
+ res, err := c.Req(req)
+ if err != nil {
+ return err
+ }
+ errd := json.NewDecoder(res.Body).Decode(&v)
+ if errd != nil {
+ return errd
+ }
+ json, errj := json.MarshalIndent(v, "", " ")
+ if errj != nil {
+ return errj
+ }
+ fmt.Println(string(json))
+
+ return nil
+ },
+}
+
func init() {
instanceCmdGroup.AddCommand(showInstanceCmd)
instanceCmdGroup.AddCommand(showPrefixInstanceCmd)
@@ -731,9 +810,11 @@ func init() {
instanceCmdGroup.AddCommand(oauthTokenInstanceCmd)
instanceCmdGroup.AddCommand(oauthRefreshTokenInstanceCmd)
instanceCmdGroup.AddCommand(oauthClientInstanceCmd)
+ instanceCmdGroup.AddCommand(findOauthClientCmd)
instanceCmdGroup.AddCommand(updateCmd)
instanceCmdGroup.AddCommand(exportCmd)
instanceCmdGroup.AddCommand(importCmd)
+ instanceCmdGroup.AddCommand(showSwiftPrefixInstanceCmd)
addInstanceCmd.Flags().StringSliceVar(&flagDomainAliases, "domain-aliases", nil, "Specify one or more aliases domain for the instance (separated by ',')")
addInstanceCmd.Flags().StringVar(&flagLocale, "locale", instance.DefaultLocale, "Locale of the new cozy instance")
addInstanceCmd.Flags().StringVar(&flagUUID, "uuid", "", "The UUID of the instance")
@@ -749,7 +830,7 @@ func init() {
addInstanceCmd.Flags().BoolVar(&flagDev, "dev", false, "To create a development instance")
addInstanceCmd.Flags().StringVar(&flagPassphrase, "passphrase", "", "Register the instance with this passphrase (useful for tests)")
modifyInstanceCmd.Flags().StringSliceVar(&flagDomainAliases, "domain-aliases", nil, "Specify one or more aliases domain for the instance (separated by ',')")
- modifyInstanceCmd.Flags().StringVar(&flagLocale, "locale", instance.DefaultLocale, "New locale")
+ modifyInstanceCmd.Flags().StringVar(&flagLocale, "locale", "", "New locale")
modifyInstanceCmd.Flags().StringVar(&flagUUID, "uuid", "", "New UUID")
modifyInstanceCmd.Flags().StringVar(&flagTOS, "tos", "", "Update the TOS version signed")
modifyInstanceCmd.Flags().StringVar(&flagTOSLatest, "tos-latest", "", "Update the latest TOS version")
@@ -763,9 +844,10 @@ func init() {
modifyInstanceCmd.Flags().BoolVar(&flagBlocked, "blocked", false, "Block the instance")
modifyInstanceCmd.Flags().BoolVar(&flagOnboardingFinished, "onboarding-finished", false, "Force the finishing of the onboarding")
destroyInstanceCmd.Flags().BoolVar(&flagForce, "force", false, "Force the deletion without asking for confirmation")
- fsckInstanceCmd.Flags().BoolVar(&flagFsckDry, "dry", false, "Don't modify the VFS, only show the inconsistencies")
- fsckInstanceCmd.Flags().BoolVar(&flagFsckPrune, "prune", false, "Try to solve inconsistencies by modifying the file system")
+ fsckInstanceCmd.Flags().BoolVar(&flagFsckIndexIntegrity, "index-indegrity", false, "Check the index integrity only")
+ fsckInstanceCmd.Flags().BoolVar(&flagJSON, "json", false, "Output more informations in JSON format")
oauthClientInstanceCmd.Flags().BoolVar(&flagJSON, "json", false, "Output more informations in JSON format")
+ oauthClientInstanceCmd.Flags().BoolVar(&flagAllowLoginScope, "allow-login-scope", false, "Allow login scope")
oauthTokenInstanceCmd.Flags().DurationVar(&flagExpire, "expire", 0, "Make the token expires in this amount of time")
appTokenInstanceCmd.Flags().DurationVar(&flagExpire, "expire", 0, "Make the token expires in this amount of time")
lsInstanceCmd.Flags().BoolVar(&flagJSON, "json", false, "Show each line as a json representation of the instance")
diff --git a/cmd/root.go b/cmd/root.go
index ce479d71e33..96357d61652 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -1,23 +1,14 @@
package cmd
import (
- "bytes"
- "crypto/sha256"
- "crypto/tls"
- "crypto/x509"
- "encoding/hex"
"errors"
"fmt"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
"os"
- "strconv"
"time"
"github.com/cozy/cozy-stack/client"
"github.com/cozy/cozy-stack/client/request"
+ "github.com/cozy/cozy-stack/client/tlsclient"
"github.com/cozy/cozy-stack/pkg/config"
"github.com/cozy/cozy-stack/pkg/permissions"
"github.com/howeyc/gopass"
@@ -57,210 +48,6 @@ profiles you.`,
SilenceErrors: true,
}
-func sslVerifyPinnedKey(fingerprint string) (func(certs [][]byte, verifiedChains [][]*x509.Certificate) error, error) {
- pinnedFingerPrint, err := hex.DecodeString(fingerprint)
- if err != nil {
- return nil, fmt.Errorf("Invalid fingerprint encoding for %s", fingerprint)
- }
-
- expected := sha256.Size
- given := len(pinnedFingerPrint)
- if given != expected {
- return nil, fmt.Errorf("Invalid fingerprint size for %s, expected %d got %d", fingerprint,
- expected, given)
- }
-
- return func(certs [][]byte, verifiedChains [][]*x509.Certificate) error {
- // Check for leaf pinning first
- for _, asn1 := range certs {
- cert, err := x509.ParseCertificate(asn1)
- if err != nil {
- return err
- }
- fingerPrint := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
- if bytes.Equal(pinnedFingerPrint, fingerPrint[:]) {
- return nil
- }
- }
-
- // Then check for intermediate pinning
- for _, verifiedChain := range verifiedChains {
- if len(verifiedChain) > 0 {
- verifiedCert := verifiedChain[0]
- fingerPrint := sha256.Sum256(verifiedCert.RawSubjectPublicKeyInfo)
- if bytes.Equal(pinnedFingerPrint, fingerPrint[:]) {
- return nil
- }
- }
- }
- return fmt.Errorf("ssl: could not find the valid pinned key from proposed ones")
- }, nil
-}
-
-func sslClient(e *endpoint) (*http.Client, error) {
- tlsConfig := &tls.Config{
- InsecureSkipVerify: !e.Validate,
- }
-
- ca := e.CA
- if ca != "" {
- data, err := ioutil.ReadFile(ca)
- if err != nil {
- return nil, fmt.Errorf("Could not read file %q: %s", ca, err)
- }
- pool := x509.NewCertPool()
- pool.AppendCertsFromPEM(data)
- tlsConfig.RootCAs = pool
- }
-
- cert := e.Cert
- key := e.Key
- if cert != "" && key != "" {
- pair, err := tls.LoadX509KeyPair(cert, key)
- if err != nil {
- return nil, fmt.Errorf("Could not read client certificate files %q and %q: %s",
- cert, key, err)
- }
- tlsConfig.Certificates = []tls.Certificate{pair}
- }
-
- fp := e.Fingerprint
- if fp != "" {
- check, err := sslVerifyPinnedKey(fp)
- if err != nil {
- return nil, err
- }
- tlsConfig.VerifyPeerCertificate = check
- }
-
- return &http.Client{
- Timeout: e.Timeout,
- Transport: &http.Transport{TLSClientConfig: tlsConfig},
- }, nil
-}
-
-type endpoint struct {
- URL *url.URL
- Cert string
- Key string
- CA string
- Fingerprint string
- Validate bool
- Timeout time.Duration
-}
-
-func (e *endpoint) generateURL(host string, port int) error {
- u, err := url.Parse(host)
- if err != nil {
- return err
- }
-
- if u.Scheme == "" {
- // We have host + port, HTTP implied
- u = &url.URL{
- Scheme: "http",
- Host: net.JoinHostPort(host, strconv.Itoa(port)),
- }
- }
-
- e.URL = u
-
- return nil
-}
-
-func (e *endpoint) configureFromURL() error {
- u := e.URL
- query := u.Query()
-
- if t := query.Get("timeout"); t != "" {
- timeout, err := time.ParseDuration(t)
- if err != nil {
- return err
- }
- e.Timeout = timeout
- }
-
- if u.Scheme == "https" {
- if t := query.Get("ca"); t != "" {
- e.CA = t
- }
- if t := query.Get("cert"); t != "" {
- e.Cert = t
- }
- if t := query.Get("key"); t != "" {
- e.Key = t
- }
- if t := query.Get("fp"); t != "" {
- e.Fingerprint = t
- }
- if t := query.Get("validate"); t != "" {
- validate, err := strconv.ParseBool(t)
- if err != nil {
- return err
- }
- e.Validate = validate
- }
- }
-
- return nil
-}
-
-func (e *endpoint) configureFromEnv(prefix string) error {
- if t := os.Getenv(prefix + "_CERT"); t != "" {
- e.Cert = t
- }
- if t := os.Getenv(prefix + "_KEY"); t != "" {
- e.Key = t
- }
- if t := os.Getenv(prefix + "_CA"); t != "" {
- e.CA = t
- }
- if t := os.Getenv(prefix + "_FINGERPRINT"); t != "" {
- e.Fingerprint = t
- }
-
- if t := os.Getenv(prefix + "_VALIDATE"); t != "" {
- validate, err := strconv.ParseBool(t)
- if err != nil {
- return err
- }
- e.Validate = validate
- }
-
- if t := os.Getenv(prefix + "_TIMEOUT"); t != "" {
- timeout, err := time.ParseDuration(t)
- if err != nil {
- return err
- }
- e.Timeout = timeout
- }
-
- return nil
-}
-
-func (e *endpoint) configure(prefix string, host string, port int) error {
- e.Validate = true
- e.Timeout = 5 * time.Minute
-
- if err := e.generateURL(host, port); err != nil {
- return err
- }
- if err := e.configureFromEnv(prefix); err != nil {
- return err
- }
- return e.configureFromURL()
-}
-
-func (e *endpoint) getClient() (*http.Client, error) {
- u := e.URL
- if u.Scheme == "https" {
- return sslClient(e)
- }
- return &http.Client{
- Timeout: e.Timeout,
- }, nil
-}
-
func newClientSafe(domain string, scopes ...string) (*client.Client, error) {
// For the CLI client, we rely on the admin APIs to generate a CLI token.
// We may want in the future rely on OAuth to handle the permissions with
@@ -276,25 +63,20 @@ func newClientSafe(domain string, scopes ...string) (*client.Client, error) {
return nil, err
}
- cfg := config.GetConfig()
- e := endpoint{}
- err = e.configure("COZY_HOST", cfg.Host, cfg.Port)
- if err != nil {
- return nil, err
- }
-
- h, err := e.getClient()
+ httpClient, clientURL, err := tlsclient.NewHTTPClient(tlsclient.HTTPEndpoint{
+ Host: config.GetConfig().Host,
+ Port: config.GetConfig().Port,
+ Timeout: 5 * time.Minute,
+ EnvPrefix: "COZY_HOST",
+ })
if err != nil {
return nil, err
}
-
- u := e.URL
-
return &client.Client{
- Scheme: u.Scheme,
- Addr: u.Host,
+ Scheme: clientURL.Scheme,
+ Addr: clientURL.Host,
Domain: domain,
- Client: h,
+ Client: httpClient,
Authorizer: &request.BearerAuthorizer{Token: token},
}, nil
}
@@ -322,25 +104,21 @@ func newAdminClient() *client.Client {
}
}
- cfg := config.GetConfig()
- e := endpoint{}
-
- err := e.configure("COZY_ADMIN", cfg.AdminHost, cfg.AdminPort)
- checkNoErr(err)
-
- h, err := e.getClient()
+ httpClient, adminURL, err := tlsclient.NewHTTPClient(tlsclient.HTTPEndpoint{
+ Host: config.GetConfig().AdminHost,
+ Port: config.GetConfig().AdminPort,
+ Timeout: 10 * time.Minute,
+ EnvPrefix: "COZY_ADMIN",
+ })
checkNoErr(err)
- u := e.URL
- c := &client.Client{
- Scheme: u.Scheme,
- Addr: u.Host,
- Domain: u.Host,
- Client: h,
+ return &client.Client{
+ Scheme: adminURL.Scheme,
+ Addr: adminURL.Host,
+ Domain: adminURL.Host,
+ Client: httpClient,
Authorizer: &request.BasicAuthorizer{Password: string(pass)},
}
-
- return c
}
func init() {
diff --git a/cmd/swift.go b/cmd/swift.go
new file mode 100644
index 00000000000..9320f8b9757
--- /dev/null
+++ b/cmd/swift.go
@@ -0,0 +1,141 @@
+package cmd
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/cozy/cozy-stack/pkg/config"
+ "github.com/cozy/cozy-stack/pkg/instance"
+ "github.com/cozy/swift"
+ "github.com/spf13/cobra"
+)
+
+var flagSwiftObjectContentType string
+
+var swiftCmdGroup = &cobra.Command{
+ Use: "swift ",
+ Short: "Interact directly with OpenStack Swift object storage",
+ PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+ if err := config.Setup(cfgFile); err != nil {
+ return err
+ }
+ if config.FsURL().Scheme != config.SchemeSwift {
+ return fmt.Errorf("swift: the configured filesystem does not rely on OpenStack Swift")
+ }
+ return config.InitSwiftConnection(config.FsURL())
+ },
+ RunE: func(cmd *cobra.Command, args []string) error {
+ return cmd.Usage()
+ },
+}
+
+var swiftGetCmd = &cobra.Command{
+ Use: "get ",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) < 2 {
+ return cmd.Usage()
+ }
+ i, err := instance.Get(args[0])
+ if err != nil {
+ return err
+ }
+ sc := config.GetSwiftConnection()
+ objectName := args[1]
+ f, _, err := sc.ObjectOpen(swiftContainer(i), objectName, false, nil)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(os.Stdout, f)
+ if err != nil {
+ return err
+ }
+ return f.Close()
+ },
+}
+
+var swiftPutCmd = &cobra.Command{
+ Use: "put ",
+ Long: `cozy-stack swift put can be used to create or update an object in
+the swift container associated to the given domain. The content of the file is
+expected on the standard input.`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) < 2 {
+ return cmd.Usage()
+ }
+ i, err := instance.Get(args[0])
+ if err != nil {
+ return err
+ }
+ sc := config.GetSwiftConnection()
+ objectName := args[1]
+ f, err := sc.ObjectCreate(swiftContainer(i), objectName, true, "", flagSwiftObjectContentType, nil)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(f, os.Stdin)
+ if err != nil {
+ return nil
+ }
+ return f.Close()
+ },
+}
+
+var swiftDeleteCmd = &cobra.Command{
+ Use: "rm ",
+ Aliases: []string{"delete"},
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) < 2 {
+ return cmd.Usage()
+ }
+ i, err := instance.Get(args[0])
+ if err != nil {
+ return err
+ }
+ sc := config.GetSwiftConnection()
+ objectName := args[1]
+ return sc.ObjectDelete(swiftContainer(i), objectName)
+ },
+}
+
+var swiftLsCmd = &cobra.Command{
+ Use: "ls ",
+ Aliases: []string{"delete"},
+ RunE: func(cmd *cobra.Command, args []string) error {
+ if len(args) < 1 {
+ return cmd.Usage()
+ }
+ i, err := instance.Get(args[0])
+ if err != nil {
+ return err
+ }
+ sc := config.GetSwiftConnection()
+ container := swiftContainer(i)
+ return sc.ObjectsWalk(container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
+ names, err := sc.ObjectNames(container, opts)
+ if err == nil {
+ fmt.Println(strings.Join(names, "\n"))
+ }
+ return names, err
+ })
+ },
+}
+
+func swiftContainer(i *instance.Instance) string {
+ if i.SwiftCluster > 0 {
+ return "cozy-v2-" + i.DBPrefix()
+ }
+ return "cozy-" + i.DBPrefix()
+}
+
+func init() {
+ swiftPutCmd.Flags().StringVar(&flagSwiftObjectContentType, "content-type", "", "Specify a Content-Type for the created object")
+
+ swiftCmdGroup.AddCommand(swiftGetCmd)
+ swiftCmdGroup.AddCommand(swiftPutCmd)
+ swiftCmdGroup.AddCommand(swiftDeleteCmd)
+ swiftCmdGroup.AddCommand(swiftLsCmd)
+
+ RootCmd.AddCommand(swiftCmdGroup)
+}
diff --git a/cozy.example.yaml b/cozy.example.yaml
index 692ae8eaa28..5dbedadc858 100644
--- a/cozy.example.yaml
+++ b/cozy.example.yaml
@@ -64,6 +64,14 @@ couchdb:
# CouchDB URL - flags: --couchdb-url
url: http://localhost:5984/
+ # CouchDB advanced parameters to activate TLS properties:
+ #
+ # root_ca: /ca-certificates.pem
+ # client_cert: /client_cert.pem
+ # client_key: /client_key
+ # pinned_key: 57c8ff33c9c0cfc3ef00e650a1cc910d7ee479a8bc509f6c9209a7c2a11399d6
+ # insecure_skip_validation: true
+
# jobs parameters to configure the job system
jobs:
# path to the imagemagick convert binary
@@ -143,7 +151,7 @@ mail:
# mail smtp port - flags: --mail-port
port: 465
# mail smtp username - flags: --mail-username
- username: {{.Env.COZY_MAIL_USER}}
+ username: {{.Env.COZY_MAIL_USERNAME}}
# mail smtp password - flags: --mail-password
password: {{.Env.COZY_MAIL_PASSWORD}}
# disable mail tls - flags: --mail-disable-tls
@@ -181,6 +189,7 @@ redis:
# databases number for each part of the stack using a specific database.
databases:
jobs: 0
+ cache: 1
lock: 2
sessions: 3
downloads: 4
@@ -201,10 +210,6 @@ redis:
# enables read only queries on slave nodes.
# read_only_slave: false
-# Auto updates scheduler
-auto_updates:
- schedule: "@cron 0 0 0 * * *"
-
# Registries used for applications and konnectors
registries:
- https://apps-registry.cozycloud.cc/
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index a7ace901b27..4aadfdd92fb 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -23,11 +23,11 @@ Opening an issue is as easy as following
[this link](https://github.com/cozy/cozy-stack/issues/new) and filling out the
fields. Here are some things you can write about your bug:
-* A short summary
-* What did you try, step by step?
-* What did you expect?
-* What did happen instead?
-* What is the version of the Cozy Stack?
+- A short summary
+- What did you try, step by step?
+- What did you expect?
+- What did happen instead?
+- What is the version of the Cozy Stack?
You can also use the [`cozy-stack bug`](cli/cozy-stack_bug.md) command to open
the form to report issue prefilled with some useful system informations.
@@ -68,9 +68,9 @@ guidelines from the Go community (gofmt,
[Effective Go](https://golang.org/doc/effective_go.html), comment the code,
etc.).
-We are using [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports)
-to format code, and [gometalinter](https://github.com/alecthomas/gometalinter)
-to detect code smells.
+We are using [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports) to
+format code, and [gometalinter](https://github.com/alecthomas/gometalinter) to
+detect code smells.
#### Step 4: Test
@@ -80,8 +80,8 @@ Don't forget to add tests and be sure they are green:
$ go test -v ./...
```
-If you want to play with the modified cozy-stack (for example, testing it with
-a webapp), you can build it locally and start it with this command:
+If you want to play with the modified cozy-stack (for example, testing it with a
+webapp), you can build it locally and start it with this command:
```
$ go build && ./cozy-stack serve
@@ -156,8 +156,8 @@ you to learn how to make your first steps here. If you have any question, don't
hesitate to ask us!
The translations are imported from transifex with `tx pull -a` in the
-`assets/locales` directory, and packed in the go code with `scripts/build.sh
-assets`.
+`assets/locales` directory, and packed in the go code with
+`scripts/build.sh assets`.
## Community
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index a8f6972895d..5cf619d04a8 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -2,11 +2,11 @@
## Dependencies
-* A reverse-proxy (nginx, caddy, haproxy, etc.)
-* A SMTP server
-* CouchDB 2
-* Git
-* Image Magick
+- A reverse-proxy (nginx, caddy, haproxy, etc.)
+- A SMTP server
+- CouchDB 2
+- Git
+- Image Magick
To install CouchDB 2 through Docker, take a look at our
[Docker specific documentation](docker.md).
@@ -32,8 +32,8 @@ You can either download the binary or compile it.
You can download a `cozy-stack` binary from our official releases:
https://github.com/cozy/cozy-stack/releases. It is a just a single executable
file (choose the one for your platform). Rename it to cozy-stack, give it the
-executable bit (`chmod +x cozy-stack`) and put it in your `$PATH`. `cozy-stack
-version` should show you the version if every thing is right.
+executable bit (`chmod +x cozy-stack`) and put it in your `$PATH`.
+`cozy-stack version` should show you the version if every thing is right.
#### Using `go`
diff --git a/docs/README.md b/docs/README.md
index df704b1fc0b..acadf89ede9 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -2,53 +2,55 @@
## Architecture
-* [General overview](architecture.md)
-* [Security](security.md)
+- [General overview](architecture.md)
+- [Security](security.md)
## Usage
-* [Install the cozy-stack](INSTALL.md)
-* [Manpages of the command-line tool](cli/cozy-stack.md)
-* [Configuration file](config.md)
-* [Managing Instances](instance.md)
-* [Onboarding](onboarding.md)
+- [Install the cozy-stack](INSTALL.md)
+- [Manpages of the command-line tool](cli/cozy-stack.md)
+- [Configuration file](config.md)
+- [Managing Instances](instance.md)
+- [Onboarding](onboarding.md)
## For developpers
-* [Develop a client-side app](client-app-dev.md)
-* [Running and building Docker images](docker.md)
-* [Build a release](release.md)
-* [The contributing guide](CONTRIBUTING.md)
+- [Develop a client-side app](client-app-dev.md)
+- [Running and building Docker images](docker.md)
+- [Build a release](release.md)
+- [The contributing guide](CONTRIBUTING.md)
## Services
-* `/auth` - [Authentication & OAuth](auth.md)
-* `/apps` - [Applications Management](apps.md)
- * [Apps registry](registry.md)
-* `/data` - [Data System](data-system.md)
- * [Mango](mango.md)
- * [Replication](replication.md)
- - [CouchDB Quirks](couchdb-quirks.md) & [PouchDB Quirks](pouchdb-quirks.md)
-* `/files` - [Virtual File System](files.md)
- * [References of documents in VFS](references-docs-in-vfs.md)
-* `/intents` - [Intents](intents.md)
-* `/jobs` - [Jobs](jobs.md)
- * [Konnectors](konnectors.md)
- * [Workers](workers.md)
-- `/move` - [Move, export and import an instance](move.md)
-* `/notifications` - [Notifications](notifications.md)
-* `/permissions` - [Permissions](permissions.md)
-* `/realtime` - [Realtime](realtime.md)
-* `/remote` - [Proxy for remote data/API](remote.md)
-* `/settings` - [Settings](settings.md)
- * [Terms of Services](user-action-required.md)
-* `/sharings` - [Sharing](sharing.md)
- * [Request for comments](sharing-design.md)
+- `/auth` - [Authentication & OAuth](auth.md)
+- `/apps` - [Applications Management](apps.md)
+ - [Apps registry](registry.md)
+ - [Konnectors](konnectors.md) &
+ [their workflow](konnectors-workflow.md)
+- `/data` - [Data System](data-system.md)
+ - [Mango](mango.md)
+ - [Replication](replication.md)
+ - [CouchDB Quirks](couchdb-quirks.md) &
+ [PouchDB Quirks](pouchdb-quirks.md)
+- `/files` - [Virtual File System](files.md)
+ - [References of documents in VFS](references-docs-in-vfs.md)
+- `/intents` - [Intents](intents.md)
+- `/jobs` - [Jobs](jobs.md)
+ - [Workers](workers.md)
+- `/move` - [Move, export and import an instance](move.md)
+- `/notifications` - [Notifications](notifications.md)
+- `/permissions` - [Permissions](permissions.md)
+- `/realtime` - [Realtime](realtime.md)
+- `/remote` - [Proxy for remote data/API](remote.md)
+- `/settings` - [Settings](settings.md)
+ - [Terms of Services](user-action-required.md)
+- `/sharings` - [Sharing](sharing.md)
+ - [Request for comments](sharing-design.md)
## Archives
These pages are the results of studies we made:
-* [Moving](moving.md)
-* [Golang Couchdb Plugins](couchdb-plugins.md)
-* [Konnectors design](konnectors_design.md)
+- [Moving](moving.md)
+- [Golang Couchdb Plugins](couchdb-plugins.md)
+- [Konnectors design](konnectors-design.md)
diff --git a/docs/account_types.md b/docs/account_types.md
deleted file mode 100644
index 5f7016f642c..00000000000
--- a/docs/account_types.md
+++ /dev/null
@@ -1,28 +0,0 @@
-[Table of contents](README.md#table-of-contents)
-
-# Account types
-
-## Google
-
-Example creation of google account_type for the stack at .mycozy.cloud
-
-* Go to https://console.developers.google.com
-* Select or Create Project (up left near the logo)
-* Enable desired APIs (TBD with usages)
-* Click "Credentials"
-* Create credentials > Oauth Client ID > Web application
-* Set redirectURI to https://oauthcallback.mycozy.cloud/accounts/google/redirect
-* Copy and paste provided Client ID and Client Secret.
-
-Then save the data in the console
-
-```
-http PUT localhost:5984/secrets%2Fio-cozy-accounts_types/google
-grant_mode=authorization_code
-redirect_uri="https://oauthcallback.mycozy.cloud/accounts/google/redirect"
-token_mode=basic
-token_endpoint="https://www.googleapis.com/oauth2/v4/token"
-auth_endpoint="https://accounts.google.com/o/oauth2/v2/auth"
-client_id=$CLIENT_ID
-client_secret=$CLIENT_SECRET
-```
diff --git a/docs/apps.md b/docs/apps.md
index bf94d451326..f851ee35053 100644
--- a/docs/apps.md
+++ b/docs/apps.md
@@ -61,20 +61,20 @@ public page on `/public`, and shared assets in `/assets`:
```json
{
- "/admin": {
- "folder": "/",
- "index": "admin.html",
- "public": false
- },
- "/public": {
- "folder": "/public",
- "index": "index.html",
- "public": true
- },
- "/assets": {
- "folder": "/assets",
- "public": true
- }
+ "/admin": {
+ "folder": "/",
+ "index": "admin.html",
+ "public": false
+ },
+ "/public": {
+ "folder": "/public",
+ "index": "index.html",
+ "public": true
+ },
+ "/assets": {
+ "folder": "/assets",
+ "public": true
+ }
}
```
@@ -83,11 +83,11 @@ route, this default one:
```json
{
- "/": {
- "folder": "/",
- "index": "index.html",
- "public": false
- }
+ "/": {
+ "folder": "/",
+ "index": "index.html",
+ "public": false
+ }
}
```
@@ -102,11 +102,11 @@ data and emit some notification or warning even without the user being on the
application. These part of the application are called services and can be
declared as part of the application in its manifest.
-In contrast to [konnectors](./konnectors.md), services have the same
-permissions as the web application and are not intended to collect outside
-informations but rather analyse the current set of collected information
-inside the cozy. However they share the same mechanisms as the konnectors to
-describe how and when they should be executed: via our trigger system.
+In contrast to [konnectors](./konnectors.md), services have the same permissions
+as the web application and are not intended to collect outside informations but
+rather analyse the current set of collected information inside the cozy. However
+they share the same mechanisms as the konnectors to describe how and when they
+should be executed: via our trigger system.
To define a service, first the code needs to be stored with the application
content, as single (packaged) javascript files. In the manifest, declare the
@@ -114,14 +114,14 @@ service and its parameters following this example:
```json
{
- "services": {
- "low-budget-notification": {
- "type": "node",
- "file": "/services/low-budget-notification.js",
- "trigger": "@cron 0 0 0 * * *"
+ "services": {
+ "low-budget-notification": {
+ "type": "node",
+ "file": "/services/low-budget-notification.js",
+ "trigger": "@cron 0 0 0 * * *"
+ }
+ // ...
}
- // ...
- }
}
```
@@ -131,25 +131,25 @@ code run and the `type` field describe the code type (only `"node"` for now).
### Notifications
-For more informations on how te declare notifications in the manifest, see
-the [notifications documentation](./notifications.md).
+For more informations on how te declare notifications in the manifest, see the
+[notifications documentation](./notifications.md).
Here is an example:
```json
{
- "notifications": {
- "account-balance": {
- "description": "Alert the user when its account balance is negative",
- "collapsible": true, // only interested in the last value of the notification
- "multiple": true, // require sub-categories for each account
- "stateful": false,
- "default_priority": "high", // high priority for this notification
- "templates": {
- "mail": "file:./notifications/account-balance-mail.tpl"
- }
+ "notifications": {
+ "account-balance": {
+ "description": "Alert the user when its account balance is negative",
+ "collapsible": true, // only interested in the last value of the notification
+ "multiple": true, // require sub-categories for each account
+ "stateful": false,
+ "default_priority": "high", // high priority for this notification
+ "templates": {
+ "mail": "file:./notifications/account-balance-mail.tpl"
+ }
+ }
}
- }
}
```
@@ -171,19 +171,19 @@ identifier on the building step of the application packages for all assets.
Here is the available sources, defined by the scheme of the source URL:
-* `registry://`: to install an application from the instance registries
-* `git://` or `git+ssh://`: to install an application from a git repository
-* `http://` or `https://`: to install an application from an http server (via a
- tarball)
-* `file://`: to install an application from a local directory (for instance:
- `file:///home/user/code/cozy-app`)
+- `registry://`: to install an application from the instance registries
+- `git://` or `git+ssh://`: to install an application from a git repository
+- `http://` or `https://`: to install an application from an http server (via
+ a tarball)
+- `file://`: to install an application from a local directory (for instance:
+ `file:///home/user/code/cozy-app`)
The `registry` scheme expect the following elements:
-* scheme: `registry`
-* host: the name of the application
-* path: `/:channel` the channel of the application (see the
- [registry](docs/registry.md) doc)
+- scheme: `registry`
+- host: the name of the application
+- path: `/:channel` the channel of the application (see the
+ [registry](docs/registry.md) doc)
Examples: `registry://drive/stable`, `registry://drive/beta`, and
`registry://drive/dev`.
@@ -210,13 +210,13 @@ application has been installed or failed.
#### Status codes
-* 202 Accepted, when the application installation has been accepted.
-* 400 Bad-Request, when the manifest of the application could not be processed
- (for instance, it is not valid JSON).
-* 404 Not Found, when the manifest or the source of the application is not
- reachable.
-* 422 Unprocessable Entity, when the sent data is invalid (for example, the slug
- is invalid or the Source parameter is not a proper or supported url)
+- 202 Accepted, when the application installation has been accepted.
+- 400 Bad-Request, when the manifest of the application could not be processed
+ (for instance, it is not valid JSON).
+- 404 Not Found, when the manifest or the source of the application is not
+ reachable.
+- 422 Unprocessable Entity, when the sent data is invalid (for example, the
+ slug is invalid or the Source parameter is not a proper or supported url)
#### Query-String
@@ -315,13 +315,13 @@ Content-Type: application/vnd.api+json
#### Status codes
-* 202 Accepted, when the application installation has been accepted.
-* 400 Bad-Request, when the manifest of the application could not be processed
- (for instance, it is not valid JSON).
-* 404 Not Found, when the application with the specified slug was not found or
- when the manifest or the source of the application is not reachable.
-* 422 Unprocessable Entity, when the sent data is invalid (for example, the slug
- is invalid or the Source parameter is not a proper or supported url)
+- 202 Accepted, when the application installation has been accepted.
+- 400 Bad-Request, when the manifest of the application could not be processed
+ (for instance, it is not valid JSON).
+- 404 Not Found, when the application with the specified slug was not found or
+ when the manifest or the source of the application is not reachable.
+- 422 Unprocessable Entity, when the sent data is invalid (for example, the
+ slug is invalid or the Source parameter is not a proper or supported url)
## List installed applications
@@ -329,12 +329,12 @@ Content-Type: application/vnd.api+json
An application can be in one of these states:
-* `installed`, the application is installed but still require some user
- interaction to accept its permissions
-* `ready`, the user can use it
-* `installing`, the installation is running and the app will soon be usable
-* `upgrading`, a new version is being installed
-* `errored`, the app is in an error state and can not be used.
+- `installed`, the application is installed but still require some user
+ interaction to accept its permissions
+- `ready`, the user can use it
+- `installing`, the installation is running and the app will soon be usable
+- `upgrading`, a new version is being installed
+- `errored`, the app is in an error state and can not be used.
#### Request
diff --git a/docs/architecture.md b/docs/architecture.md
index 9bc331fdaab..2a315d28785 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -1,6 +1,6 @@
[Table of contents](README.md#table-of-contents)
-# Cozy Architecture
+# Cozy Stack Architecture
## What is Cozy?
@@ -15,23 +15,23 @@ as 4 layers, from inside to outside:
It's also a set of values: Simple, Versatile, Yours. These values mean a lot for
Cozy in all aspects. From an architectural point of view, it declines to:
-* Simple to deploy and understand, not built as a galaxy of optimized
- microservices managed by kubernetes that only experts can debug.
-* Versatile, can be hosted on a Raspberry Pi for geeks to massive scale on
- multiple servers by specialized hosting. Users can install apps.
-* Yours, you own your data and you control it. If you want to take back your
- data to go elsewhere, you can.
+- Simple to deploy and understand, not built as a galaxy of optimized
+ microservices managed by kubernetes that only experts can debug.
+- Versatile, can be hosted on a Raspberry Pi for geeks to massive scale on
+ multiple servers by specialized hosting. Users can install apps.
+- Yours, you own your data and you control it. If you want to take back your
+ data to go elsewhere, you can.
## Overview
The architecture of Cozy is composed of:
-* A reverse proxy
-* The cozy stack
-* A CouchDB instance to persist the JSON documents
-* A space for storing files
-* Optionally, Redis for caching and synchronization
-* Optionally, a metrics server.
+- A reverse proxy
+- The cozy stack
+- A CouchDB instance to persist the JSON documents
+- A space for storing files
+- Optionally, Redis for caching and synchronization
+- Optionally, a metrics server.
All of this can run on a personal server, self-hosted at home, like a Raspberry
Pi:
@@ -51,12 +51,12 @@ availability:
This elasticity comes with some constraints:
-* Most applications are run in the browser, not in the server.
-* What must run on the server is mutualized inside the cozy stack.
-* The cozy stack is stateless.
-* The data is stored in couchdb and a space for files.
-* A couchdb database is specific to an instance (no mix of data from 2 users in
- the same database).
+- Most applications are run in the browser, not in the server.
+- What must run on the server is mutualized inside the cozy stack.
+- The cozy stack is stateless.
+- The data is stored in couchdb and a space for files.
+- A couchdb database is specific to an instance (no mix of data from 2 users
+ in the same database).
### Reverse proxy
@@ -141,8 +141,8 @@ developers to create their own apps.
The cozy stack can run in several modes, set by a UNIX environment variable:
-* `production`, the default
-* `development`, for coding on the cozy stack.
+- `production`, the default
+- `development`, for coding on the cozy stack.
This mode is set when compiling the cozy-stack. It is used to show more or less
logs, and what is acceptable to be displayed in errors.
@@ -202,9 +202,9 @@ It's possible to store files on the cozy, including binary ones like photos and
movies, thanks to the virtual file system. It's a facade, with several
implementations, depending on where the files are effectively stored:
-* In a directory of a local file system (easier for self-hosted users)
-* Swift from Open Stack (convenient for massive hosting)
-* And more storage providers, like [minio](https://minio.io/), later.
+- In a directory of a local file system (easier for self-hosted users)
+- Swift from Open Stack (convenient for massive hosting)
+- And more storage providers, like [minio](https://minio.io/), later.
The range of possible operations with this endpoint goes from simple ones, like
uploading a file, to more complex ones, like renaming a folder. It also ensure
@@ -393,10 +393,10 @@ files in a cozy instance with a laptop or desktop.
Go (often referred as golang) is an open source programming language created at
Google in 2007. It has nice properties for our usage:
-* Simplicity (the language can be learned in weeks, not years).
-* A focus on productivity.
-* Good performance.
-* A good support of concurrency with channels and goroutines.
+- Simplicity (the language can be learned in weeks, not years).
+- A focus on productivity.
+- Good performance.
+- A good support of concurrency with channels and goroutines.
Moreover, Go is
[used by a lot of companies](https://github.com/golang/go/wiki/GoUsers), is in
@@ -442,17 +442,17 @@ The golang web framework used for the cozy stack is
There are some HTTP status codes that are generally used in the API:
-* 200 OK, when everything is OK
-* 201 Created, when a resource was created
-* 204 No Content, when a resource was deleted
-* 400 Bad Request, when the request has some unknown parameters and the request
- body is not in the expected format
-* 401 Unauthorized, when the user is not authenticated
-* 403 Forbidden, when the permissions forbid this action
-* 404 Not Found, when the resouce can't be found
-* 500 Internal Server Error, when a bug occurs
-* 503 Service Unavailable, when the stack, CouchDB, Redis or Swift is
- unavailable.
+- 200 OK, when everything is OK
+- 201 Created, when a resource was created
+- 204 No Content, when a resource was deleted
+- 400 Bad Request, when the request has some unknown parameters and the
+ request body is not in the expected format
+- 401 Unauthorized, when the user is not authenticated
+- 403 Forbidden, when the permissions forbid this action
+- 404 Not Found, when the resouce can't be found
+- 500 Internal Server Error, when a bug occurs
+- 503 Service Unavailable, when the stack, CouchDB, Redis or Swift is
+ unavailable.
### DocTypes
@@ -461,11 +461,11 @@ of thing it is. For example, a contact will have the docType `io.cozy.contacts`,
and in the cozy-doctypes repository, there will be a contacts JSON file inside
it that describes this doctype:
-* What are the mandatory and optional fields?
-* What is the type (string, integer, date) of the fields?
-* Is there a validation rule for a field?
-* How the fields can be indexed for full text search?
-* What is the role of each field (documentation)?
+- What are the mandatory and optional fields?
+- What is the type (string, integer, date) of the fields?
+- Is there a validation rule for a field?
+- How the fields can be indexed for full text search?
+- What is the role of each field (documentation)?
This description can be used by any cozy client library (JS, Golang, etc.) to
generate some models to simplify the use of documents of this doctype.
@@ -509,13 +509,13 @@ One of the goals of the new architecture is to make it easier for developers to
write new apps. It means having a good documentation, but also some devtools to
help:
-* The `cozy` executable will have a command to setup a new project.
-* The devtools on the cozy interface will give documentation about the doctypes,
- help explore the Rest API, and check if the permissions are OK.
-* `cozy-ui` will make it easy to reuse some widgets and offer an application
- with a style coherent to the cozy identity.
-* Some docTypes with heavy logic will be available as JS classes to be reused in
- the apps.
+- The `cozy` executable will have a command to setup a new project.
+- The devtools on the cozy interface will give documentation about the
+ doctypes, help explore the Rest API, and check if the permissions are OK.
+- `cozy-ui` will make it easy to reuse some widgets and offer an application
+ with a style coherent to the cozy identity.
+- Some docTypes with heavy logic will be available as JS classes to be reused
+ in the apps.
#### Reporting a bug or suggesting a new feature
@@ -549,10 +549,10 @@ applications in a different server, or maybe in docker.
The Cozy Stack will have no auto-update mechanism. For installing and updating
it, you can use the classical ways:
-* Using a package manager, like apt for debian & ubuntu.
-* Using an official image for Raspberry Pi (and other embedded platforms).
-* Using the image and services of an hosting company.
-* Or compiling and installing it manually if you are really brave ;-)
+- Using a package manager, like apt for debian & ubuntu.
+- Using an official image for Raspberry Pi (and other embedded platforms).
+- Using the image and services of an hosting company.
+- Or compiling and installing it manually if you are really brave ;-)
> How to add a cozy instance to a farm?
@@ -575,9 +575,9 @@ looks too complicated for a temporary thing.
There are 2 sensitive places with data:
-* In CouchDB.
-* on the place used for the Virtual File System (a directory on the local
- filesystem, or in Swift).
+- In CouchDB.
+- on the place used for the Virtual File System (a directory on the local
+ filesystem, or in Swift).
You can use the tools of your choice to backup these 2 locations. The good old
rsync works fine (CouchDB files are append-only, except when compaction happens,
@@ -593,10 +593,10 @@ instance to another, and so, it can be used as a backup.
Yes, it's often easier to scale by separating concerns, and microservices is a
way to achieve that. But, it has some serious downsides:
-* It takes more memory and it's probably a no-go for Raspberry Pi.
-* It's more complicated for a developper to install the whole stack before
- coding its application.
-* It's harder to deploy in production.
+- It takes more memory and it's probably a no-go for Raspberry Pi.
+- It's more complicated for a developper to install the whole stack before
+ coding its application.
+- It's harder to deploy in production.
For the scalability, we can also deploy some specialized instances of the Cozy
Stack. For example, we can have some Cozy Stack processes dedicated for
@@ -608,9 +608,9 @@ trafic from the load-balancer.
If you want to develop your own app, you can use the framework and the tools you
like, nothing is mandatory. For the official apps, we will want to move to:
-* es2017 (but converting the existing coffeescript code will take time)
-* npm scripts and webpack
-* preact & JSX.
+- es2017 (but converting the existing coffeescript code will take time)
+- npm scripts and webpack
+- preact & JSX.
More about this
[here](https://forum.cozy.io/t/a-propos-de-la-pile-technique-front-about-our-frontend-stack/3849/1)
diff --git a/docs/auth.md b/docs/auth.md
index f8b191be003..69240a61137 100644
--- a/docs/auth.md
+++ b/docs/auth.md
@@ -14,11 +14,12 @@ OAuth2 is about delegating an access to resources on a server to another party.
It is a framework, not a strictly defined protocol, for organizing the
interactions between these 4 actors:
-* the resource owner, the "user" that can click on buttons
-* the client, the website or application that would like to access the resources
-* the authorization server, whose role is limited to give tokens but is central
- in OAuth2 interactions
-* the resources server, the server that controls the resources.
+- the resource owner, the "user" that can click on buttons
+- the client, the website or application that would like to access the
+ resources
+- the authorization server, whose role is limited to give tokens but is
+ central in OAuth2 interactions
+- the resources server, the server that controls the resources.
For cozy, both the authorization server and the resources server roles are
played by the cozy-stack. The resource owner is the owner of a cozy instance.
@@ -29,10 +30,10 @@ letting the client get a token issued by the authorization server, and using
this token to access to the resources. OAuth2 describe 4 flows, called grant
types, for the first part:
-* Authorization code
-* Implicit grant type
-* Client credentials grant type
-* Resource owner credentials grant type.
+- Authorization code
+- Implicit grant type
+- Client credentials grant type
+- Resource owner credentials grant type.
On cozy, only the most typical one is used: authorization code. To start this
flow, the client must have a `client_id` and `client_secret`. The Cozy stack
@@ -41,34 +42,34 @@ OAuth2) to allow the clients to obtain them.
OAuth2 has also 3 ways to use a token:
-* in the query-string (even if the spec does not recommended it)
-* in the POST body
-* in the HTTP Authorization header.
+- in the query-string (even if the spec does not recommended it)
+- in the POST body
+- in the HTTP Authorization header.
On cozy, only the HTTP header is supported.
OAuth2 has a lot of assumptions. Let's see some of them and their consequences
on Cozy:
-* TLS is very important to secure the communications. in OAuth 1, there was a
- mechanism to sign the requests. But it was very difficult to get it right for
- the developers and was abandonned in OAuth2, in favor of using TLS. The Cozy
- instance are already accessible only in HTTPS, so there is nothing particular
- to do for that.
+- TLS is very important to secure the communications. in OAuth 1, there was a
+ mechanism to sign the requests. But it was very difficult to get it right
+ for the developers and was abandonned in OAuth2, in favor of using TLS. The
+ Cozy instance are already accessible only in HTTPS, so there is nothing
+ particular to do for that.
-* There is a principle called TOFU, Trust On First Use. It said that if the user
- will give his permission for delegating access to its resources when the
- client will try to access them for the first time. Later, the client will be
- able to keep accessing them even if the user is no longer here to give his
- permissions.
+- There is a principle called TOFU, Trust On First Use. It said that if the
+ user will give his permission for delegating access to its resources when
+ the client will try to access them for the first time. Later, the client
+ will be able to keep accessing them even if the user is no longer here to
+ give his permissions.
-* The client can't make the assumptions about when its tokens will work. The
- tokens have no meaning for him (like cookies in a browser), they are just
- something it got from the authorization server and can send with its request.
- The access token can expire, the user can revoke them, etc.
+- The client can't make the assumptions about when its tokens will work. The
+ tokens have no meaning for him (like cookies in a browser), they are just
+ something it got from the authorization server and can send with its
+ request. The access token can expire, the user can revoke them, etc.
-* OAuth 2.0 defines no cryptographic methods. But a developer that want to use
- it will have to put her hands in that.
+- OAuth 2.0 defines no cryptographic methods. But a developer that want to use
+ it will have to put her hands in that.
If you want to learn OAuth 2 in details, I recommend the
[OAuth 2 in Action book](https://www.manning.com/books/oauth-2-in-action).
@@ -253,36 +254,37 @@ for the details.
The client must send a JSON request, with at least:
-* `redirect_uris`, an array of strings with the redirect URIs that the client
- will use in the authorization flow
-* `client_name`, human-readable string name of the client to be presented to the
- end-user during authorization
-* `software_id`, an identifier of the software used by the client (it should
- remain the same for all instances of the client software, whereas `client_id`
- varies between instances).
+- `redirect_uris`, an array of strings with the redirect URIs that the client
+ will use in the authorization flow
+- `client_name`, human-readable string name of the client to be presented to
+ the end-user during authorization
+- `software_id`, an identifier of the software used by the client (it should
+ remain the same for all instances of the client software, whereas
+ `client_id` varies between instances).
It can also send the optional fields:
-* `client_kind` (possible values: web, desktop, mobile, browser, etc.)
-* `client_uri`, URL string of a web page providing information about the client
-* `logo_uri`, to display an icon to the user in the authorization flow
-* `policy_uri`, URL string that points to a human-readable privacy policy
- document that describes how the deployment organization collects, uses,
- retains, and discloses personal data
-* `software_version`, a version identifier string for the client software.
-* `notification_platform`, to activate notifications on the associated
- device, this field specify the platform used to send notifications:
- * `"android"`: for Android devices with notifications via Firebase Cloud
- Messageing
- * `"ios"`: for iOS devices with notifications via APNS/2.
-* `notification_device_token`, the token used to identify the mobile device
- for notifications
+- `client_kind` (possible values: web, desktop, mobile, browser, etc.)
+- `client_uri`, URL string of a web page providing information about the
+ client
+- `logo_uri`, to display an icon to the user in the authorization flow
+- `policy_uri`, URL string that points to a human-readable privacy policy
+ document that describes how the deployment organization collects, uses,
+ retains, and discloses personal data
+- `software_version`, a version identifier string for the client software.
+- `notification_platform`, to activate notifications on the associated device,
+ this field specify the platform used to send notifications:
+ - `"android"`: for Android devices with notifications via Firebase Cloud
+ Messageing
+ - `"ios"`: for iOS devices with notifications via APNS/2.
+- `notification_device_token`, the token used to identify the mobile device
+ for notifications
The server gives to the client the previous fields and these informations:
-* `client_id`
-* `client_secret`
-* `registration_access_token`
+- `client_id`
+- `client_secret`
+- `registration_access_token`
Example:
@@ -295,14 +297,14 @@ Accept: application/json
```json
{
- "redirect_uris": ["https://client.example.org/oauth/callback"],
- "client_name": "Client",
- "software_id": "github.com/example/client",
- "software_version": "2.0.1",
- "client_kind": "web",
- "client_uri": "https://client.example.org/",
- "logo_uri": "https://client.example.org/logo.svg",
- "policy_uri": "https://client/example.org/policy"
+ "redirect_uris": ["https://client.example.org/oauth/callback"],
+ "client_name": "Client",
+ "software_id": "github.com/example/client",
+ "software_version": "2.0.1",
+ "client_kind": "web",
+ "client_uri": "https://client.example.org/",
+ "logo_uri": "https://client.example.org/logo.svg",
+ "policy_uri": "https://client/example.org/policy"
}
```
@@ -313,20 +315,20 @@ Content-Type: application/json
```json
{
- "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
- "client_secret": "eyJpc3Mi[...omitted for brevity...]",
- "client_secret_expires_at": 0,
- "registration_access_token": "J9l-ZhwP[...omitted for brevity...]",
- "grant_types": ["authorization_code", "refresh_token"],
- "response_types": ["code"],
- "redirect_uris": ["https://client.example.org/oauth/callback"],
- "client_name": "Client",
- "software_id": "github.com/example/client",
- "software_version": "2.0.1",
- "client_kind": "web",
- "client_uri": "https://client.example.org/",
- "logo_uri": "https://client.example.org/logo.svg",
- "policy_uri": "https://client/example.org/policy"
+ "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
+ "client_secret": "eyJpc3Mi[...omitted for brevity...]",
+ "client_secret_expires_at": 0,
+ "registration_access_token": "J9l-ZhwP[...omitted for brevity...]",
+ "grant_types": ["authorization_code", "refresh_token"],
+ "response_types": ["code"],
+ "redirect_uris": ["https://client.example.org/oauth/callback"],
+ "client_name": "Client",
+ "software_id": "github.com/example/client",
+ "software_version": "2.0.1",
+ "client_kind": "web",
+ "client_uri": "https://client.example.org/",
+ "logo_uri": "https://client.example.org/logo.svg",
+ "policy_uri": "https://client/example.org/policy"
}
```
@@ -354,19 +356,19 @@ Content-Type: application/json
```json
{
- "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
- "client_secret": "eyJpc3Mi[...omitted for brevity...]",
- "client_secret_expires_at": 0,
- "grant_types": ["authorization_code", "refresh_token"],
- "response_types": ["code"],
- "redirect_uris": ["https://client.example.org/oauth/callback"],
- "client_name": "Client",
- "software_id": "github.com/example/client",
- "software_version": "2.0.1",
- "client_kind": "web",
- "client_uri": "https://client.example.org/",
- "logo_uri": "https://client.example.org/logo.svg",
- "policy_uri": "https://client/example.org/policy"
+ "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
+ "client_secret": "eyJpc3Mi[...omitted for brevity...]",
+ "client_secret_expires_at": 0,
+ "grant_types": ["authorization_code", "refresh_token"],
+ "response_types": ["code"],
+ "redirect_uris": ["https://client.example.org/oauth/callback"],
+ "client_name": "Client",
+ "software_id": "github.com/example/client",
+ "software_version": "2.0.1",
+ "client_kind": "web",
+ "client_uri": "https://client.example.org/",
+ "logo_uri": "https://client.example.org/logo.svg",
+ "policy_uri": "https://client/example.org/policy"
}
```
@@ -390,18 +392,18 @@ Authorization: Bearer J9l-ZhwP...
```json
{
- "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
- "client_secret": "eyJpc3Mi[...omitted for brevity...]",
- "redirect_uris": ["https://client.example.org/oauth/callback"],
- "client_name": "Client",
- "software_id": "github.com/example/client",
- "software_version": "2.0.2",
- "client_kind": "web",
- "client_uri": "https://client.example.org/",
- "logo_uri": "https://client.example.org/client-logo.svg",
- "policy_uri": "https://client/example.org/policy",
- "notification_platform": "android",
- "notification_device_token": "XXXXxxxx..."
+ "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
+ "client_secret": "eyJpc3Mi[...omitted for brevity...]",
+ "redirect_uris": ["https://client.example.org/oauth/callback"],
+ "client_name": "Client",
+ "software_id": "github.com/example/client",
+ "software_version": "2.0.2",
+ "client_kind": "web",
+ "client_uri": "https://client.example.org/",
+ "logo_uri": "https://client.example.org/client-logo.svg",
+ "policy_uri": "https://client/example.org/policy",
+ "notification_platform": "android",
+ "notification_device_token": "XXXXxxxx..."
}
```
@@ -412,19 +414,19 @@ Content-Type: application/json
```json
{
- "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
- "client_secret": "IFais2Ah[...omitted for brevity...]",
- "client_secret_expires_at": 0,
- "grant_types": ["authorization_code", "refresh_token"],
- "response_types": ["code"],
- "redirect_uris": ["https://client.example.org/oauth/callback"],
- "client_name": "Client",
- "software_id": "github.com/example/client",
- "software_version": "2.0.2",
- "client_kind": "web",
- "client_uri": "https://client.example.org/",
- "logo_uri": "https://client.example.org/client-logo.svg",
- "policy_uri": "https://client/example.org/policy"
+ "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3",
+ "client_secret": "IFais2Ah[...omitted for brevity...]",
+ "client_secret_expires_at": 0,
+ "grant_types": ["authorization_code", "refresh_token"],
+ "response_types": ["code"],
+ "redirect_uris": ["https://client.example.org/oauth/callback"],
+ "client_name": "Client",
+ "software_id": "github.com/example/client",
+ "software_version": "2.0.2",
+ "client_kind": "web",
+ "client_uri": "https://client.example.org/",
+ "logo_uri": "https://client.example.org/client-logo.svg",
+ "policy_uri": "https://client/example.org/policy"
}
```
@@ -452,15 +454,16 @@ and has an accept button if she is OK with that.
The parameters are:
-* `client_id`, that identify the client
-* `redirect_uri`, it has to be exactly the same as the one used in registration
-* `state`, it's a protection against CSRF on the client (a random string
- generated by the client, that it can check when the user will be redirected
- with the authorization code. It can be used as a key in local storage for
- storing a state in a SPA).
-* `response_type`, only `code` is supported
-* `scope`, a space separated list of the [permissions](permissions.md) asked
- (like `io.cozy.files:GET` for read-only access to files).
+- `client_id`, that identify the client
+- `redirect_uri`, it has to be exactly the same as the one used in
+ registration
+- `state`, it's a protection against CSRF on the client (a random string
+ generated by the client, that it can check when the user will be redirected
+ with the authorization code. It can be used as a key in local storage for
+ storing a state in a SPA).
+- `response_type`, only `code` is supported
+- `scope`, a space separated list of the [permissions](permissions.md) asked
+ (like `io.cozy.files:GET` for read-only access to files).
```http
GET /auth/authorize?client_id=oauth-client-1&response_type=code&scope=io.cozy.files:GET%20io.cozy.contacts&state=Eh6ahshepei5Oojo&redirect_uri=https%3A%2F%2Fclient.org%2F HTTP/1.1
@@ -509,10 +512,10 @@ This endpoint is also used to refresh the access token, by sending the
The parameters are:
-* `grant_type`, with `authorization_code` or `refresh_token` as value
-* `code` or `refresh_token`, depending on which grant type is used
-* `client_id`
-* `client_secret`
+- `grant_type`, with `authorization_code` or `refresh_token` as value
+- `code` or `refresh_token`, depending on which grant type is used
+- `client_id`
+- `client_secret`
Example:
@@ -578,10 +581,10 @@ Here is how it works in more details:
On each connection, when the 2FA is activated, the user is asked for its
passphrase first. When entering correct passphrase, the user is then asked for:
-* a TOTP (Timebased One-Time password, RFC 6238) derived from a secret
- associated with the instance.
-* a short term timestamped MAC with the same validity time-range and also
- derived from the same secret.
+- a TOTP (Timebased One-Time password, RFC 6238) derived from a secret
+ associated with the instance.
+- a short term timestamped MAC with the same validity time-range and also
+ derived from the same secret.
The TOTP is valid for a time range of about 5 minutes. When sending a correct
and still-valid pair `(passcode, token)`, the user is granted with
@@ -631,9 +634,9 @@ cookie. A redirection will still happen to remove the code from the URL (it
helps to avoid the code being saved in the browser history). For security
reasons, the session code have the following properties:
-* It can only be used once.
-* It is tied to an application (`calendar` in our example).
-* It has a very short time span of validity (1 minute).
+- It can only be used once.
+- It is tied to an application (`calendar` in our example).
+- It has a very short time span of validity (1 minute).
### How to use a token?
@@ -676,9 +679,9 @@ explained [above](#post-authregister).
To get an access token, it's enough to follow the authorization code flow of
OAuth2:
-* sending the user to the cozy, on the authorize page
-* if the user approves, she is then redirected back to the client
-* the client gets the access code and can exchange it to an access token.
+- sending the user to the cozy, on the authorize page
+- if the user approves, she is then redirected back to the client
+- the client gets the access code and can exchange it to an access token.
### How to use a token?
@@ -765,11 +768,11 @@ flow. But it is mandatory to use it with Cozy.
For more on this subject, here is a list of links:
-* https://www.owasp.org/index.php/Authentication_Cheat_Sheet
-* https://tools.ietf.org/html/rfc6749#page-53
-* https://tools.ietf.org/html/rfc6819
-* https://tools.ietf.org/html/draft-ietf-oauth-closing-redirectors-00
-* http://www.oauthsecurity.com/
+- https://www.owasp.org/index.php/Authentication_Cheat_Sheet
+- https://tools.ietf.org/html/rfc6749#page-53
+- https://tools.ietf.org/html/rfc6819
+- https://tools.ietf.org/html/draft-ietf-oauth-closing-redirectors-00
+- http://www.oauthsecurity.com/
## Conclusion
diff --git a/docs/cli/cozy-stack.md b/docs/cli/cozy-stack.md
index dd8e6ebaad6..e19ef4c541d 100644
--- a/docs/cli/cozy-stack.md
+++ b/docs/cli/cozy-stack.md
@@ -39,6 +39,7 @@ cozy-stack [flags]
* [cozy-stack serve](cozy-stack_serve.md) - Starts the stack and listens for HTTP calls
* [cozy-stack settings](cozy-stack_settings.md) - Display and update settings
* [cozy-stack status](cozy-stack_status.md) - Check if the HTTP server is running
+* [cozy-stack swift](cozy-stack_swift.md) - Interact directly with OpenStack Swift object storage
* [cozy-stack triggers](cozy-stack_triggers.md) - Interact with the triggers
* [cozy-stack version](cozy-stack_version.md) - Print the version number
diff --git a/docs/cli/cozy-stack_config.md b/docs/cli/cozy-stack_config.md
index 280d00c7c82..7fd0eee2a39 100644
--- a/docs/cli/cozy-stack_config.md
+++ b/docs/cli/cozy-stack_config.md
@@ -28,7 +28,12 @@ cozy-stack config allows to print and generate some parts of the configuration
* [cozy-stack](cozy-stack.md) - cozy-stack is the main command
* [cozy-stack config decrypt-creds](cozy-stack_config_decrypt-creds.md) - Decrypt the given credentials cipher text with the specified decryption keyfile.
+* [cozy-stack config decrypt-data](cozy-stack_config_decrypt-data.md) - Decrypt data with the specified decryption keyfile.
+* [cozy-stack config encrypt-creds](cozy-stack_config_encrypt-creds.md) - Encrypt the given credentials with the specified decryption keyfile.
+* [cozy-stack config encrypt-data](cozy-stack_config_encrypt-data.md) - Encrypt data with the specified encryption keyfile.
* [cozy-stack config gen-keys](cozy-stack_config_gen-keys.md) - Generate an key pair for encryption and decryption of credentials
+* [cozy-stack config insert-asset](cozy-stack_config_insert-asset.md) - Inserts an asset
+* [cozy-stack config ls-assets](cozy-stack_config_ls-assets.md) - List assets
* [cozy-stack config passwd](cozy-stack_config_passwd.md) - Generate an admin passphrase
* [cozy-stack config print](cozy-stack_config_print.md) - Display the configuration
diff --git a/docs/cli/cozy-stack_config_decrypt-data.md b/docs/cli/cozy-stack_config_decrypt-data.md
new file mode 100644
index 00000000000..67e0e1492f9
--- /dev/null
+++ b/docs/cli/cozy-stack_config_decrypt-data.md
@@ -0,0 +1,32 @@
+## cozy-stack config decrypt-data
+
+Decrypt data with the specified decryption keyfile.
+
+### Synopsis
+
+Decrypt data with the specified decryption keyfile.
+
+```
+cozy-stack config decrypt-data [flags]
+```
+
+### Options
+
+```
+ -h, --help help for decrypt-data
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack config](cozy-stack_config.md) - Show and manage configuration elements
+
diff --git a/docs/cli/cozy-stack_config_encrypt-creds.md b/docs/cli/cozy-stack_config_encrypt-creds.md
new file mode 100644
index 00000000000..0cafdec2aa7
--- /dev/null
+++ b/docs/cli/cozy-stack_config_encrypt-creds.md
@@ -0,0 +1,32 @@
+## cozy-stack config encrypt-creds
+
+Encrypt the given credentials with the specified decryption keyfile.
+
+### Synopsis
+
+Encrypt the given credentials with the specified decryption keyfile.
+
+```
+cozy-stack config encrypt-creds [flags]
+```
+
+### Options
+
+```
+ -h, --help help for encrypt-creds
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack config](cozy-stack_config.md) - Show and manage configuration elements
+
diff --git a/docs/cli/cozy-stack_config_encrypt-data.md b/docs/cli/cozy-stack_config_encrypt-data.md
new file mode 100644
index 00000000000..7e19d797211
--- /dev/null
+++ b/docs/cli/cozy-stack_config_encrypt-data.md
@@ -0,0 +1,41 @@
+## cozy-stack config encrypt-data
+
+Encrypt data with the specified encryption keyfile.
+
+### Synopsis
+
+cozy-stack config encrypt-data encrypts any valid JSON data
+
+```
+cozy-stack config encrypt-data [flags]
+```
+
+### Examples
+
+```
+
+$ ./cozy-stack config encrypt-data ~/.cozy/key.enc "{\"foo\": \"bar\"}"
+$ bmFjbNFjY+XZkS26YtVPUIKKm/JdnAGwG30n6A4ypS1p1dHev8hOtaRbW+lGneoO7PS9JCW8U5GSXhASu+c3UkaZ
+
+```
+
+### Options
+
+```
+ -h, --help help for encrypt-data
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack config](cozy-stack_config.md) - Show and manage configuration elements
+
diff --git a/docs/cli/cozy-stack_config_gen-keys.md b/docs/cli/cozy-stack_config_gen-keys.md
index 4c353d75ffc..cd9d7e12ad9 100644
--- a/docs/cli/cozy-stack_config_gen-keys.md
+++ b/docs/cli/cozy-stack_config_gen-keys.md
@@ -13,14 +13,18 @@ The encryptor key filename is given the ".enc" extension suffix.
The files permissions are 0400.
-example: cozy-stack config gen-keys ~/credentials-key
+```
+cozy-stack config gen-keys [flags]
+```
+
+### Examples
+
+```
+$ cozy-stack config gen-keys ~/credentials-key
keyfiles written in:
~/credentials-key.enc
~/credentials-key.dec
-
-```
-cozy-stack config gen-keys [flags]
```
### Options
diff --git a/docs/cli/cozy-stack_config_insert-asset.md b/docs/cli/cozy-stack_config_insert-asset.md
new file mode 100644
index 00000000000..7d8d95c28a9
--- /dev/null
+++ b/docs/cli/cozy-stack_config_insert-asset.md
@@ -0,0 +1,42 @@
+## cozy-stack config insert-asset
+
+Inserts an asset
+
+### Synopsis
+
+Inserts a custom asset in a specific context
+
+```
+cozy-stack config insert-asset --url --name --shasum --context [flags]
+```
+
+### Examples
+
+```
+$ cozy-stack config insert-asset --url file:///foo/bar/baz.js --name /foo/bar/baz.js --shasum 0763d6c2cebee0880eb3a9cc25d38cd23db39b5c3802f2dc379e408c877a2788 --context foocontext
+```
+
+### Options
+
+```
+ --context string The context of the asset
+ -h, --help help for insert-asset
+ --name string The name of the asset
+ --shasum string The shasum of the asset
+ --url string The URL of the asset
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack config](cozy-stack_config.md) - Show and manage configuration elements
+
diff --git a/docs/cli/cozy-stack_config_ls-assets.md b/docs/cli/cozy-stack_config_ls-assets.md
new file mode 100644
index 00000000000..ad48db132c3
--- /dev/null
+++ b/docs/cli/cozy-stack_config_ls-assets.md
@@ -0,0 +1,38 @@
+## cozy-stack config ls-assets
+
+List assets
+
+### Synopsis
+
+List assets currently served by the stack
+
+```
+cozy-stack config ls-assets [flags]
+```
+
+### Examples
+
+```
+$ cozy-stack config ls-assets
+```
+
+### Options
+
+```
+ -h, --help help for ls-assets
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack config](cozy-stack_config.md) - Show and manage configuration elements
+
diff --git a/docs/cli/cozy-stack_fixer.md b/docs/cli/cozy-stack_fixer.md
index 0ed9bde1835..3023f475e3d 100644
--- a/docs/cli/cozy-stack_fixer.md
+++ b/docs/cli/cozy-stack_fixer.md
@@ -29,8 +29,8 @@ cozy-stack fixer [flags]
### SEE ALSO
* [cozy-stack](cozy-stack.md) - cozy-stack is the main command
-* [cozy-stack fixer accounts-orphans](cozy-stack_fixer_accounts-orphans.md) - Rebuild triggers associated with orphan accounts
* [cozy-stack fixer albums-created-at](cozy-stack_fixer_albums-created-at.md) - Add a created_at field for albums where it's missing
+* [cozy-stack fixer contact-emails](cozy-stack_fixer_contact-emails.md) - Detect and try to fix invalid emails on contacts
* [cozy-stack fixer jobs](cozy-stack_fixer_jobs.md) - Take a look at the consistency of the jobs
* [cozy-stack fixer md5](cozy-stack_fixer_md5.md) - Fix missing md5 from contents in the vfs
* [cozy-stack fixer mime](cozy-stack_fixer_mime.md) - Fix the class computed from the mime-type
diff --git a/docs/cli/cozy-stack_fixer_accounts-orphans.md b/docs/cli/cozy-stack_fixer_contact-emails.md
similarity index 69%
rename from docs/cli/cozy-stack_fixer_accounts-orphans.md
rename to docs/cli/cozy-stack_fixer_contact-emails.md
index ddbcc6a1431..b559e8b333e 100644
--- a/docs/cli/cozy-stack_fixer_accounts-orphans.md
+++ b/docs/cli/cozy-stack_fixer_contact-emails.md
@@ -1,20 +1,19 @@
-## cozy-stack fixer accounts-orphans
+## cozy-stack fixer contact-emails
-Rebuild triggers associated with orphan accounts
+Detect and try to fix invalid emails on contacts
### Synopsis
-Rebuild triggers associated with orphan accounts
+Detect and try to fix invalid emails on contacts
```
-cozy-stack fixer accounts-orphans [flags]
+cozy-stack fixer contact-emails [flags]
```
### Options
```
- --dry-run Dry run
- -h, --help help for accounts-orphans
+ -h, --help help for contact-emails
```
### Options inherited from parent commands
diff --git a/docs/cli/cozy-stack_instances.md b/docs/cli/cozy-stack_instances.md
index 0671b398c0f..b9f8c29ad12 100644
--- a/docs/cli/cozy-stack_instances.md
+++ b/docs/cli/cozy-stack_instances.md
@@ -43,6 +43,7 @@ cozy-stack instances [flags]
* [cozy-stack instances debug](cozy-stack_instances_debug.md) - Activate or deactivate debugging of the instance
* [cozy-stack instances destroy](cozy-stack_instances_destroy.md) - Remove instance
* [cozy-stack instances export](cozy-stack_instances_export.md) - Export an instance to a tarball
+* [cozy-stack instances find-oauth-client](cozy-stack_instances_find-oauth-client.md) - Find an OAuth client
* [cozy-stack instances fsck](cozy-stack_instances_fsck.md) - Check and repair a vfs
* [cozy-stack instances import](cozy-stack_instances_import.md) - Import a tarball
* [cozy-stack instances ls](cozy-stack_instances_ls.md) - List instances
@@ -50,6 +51,8 @@ cozy-stack instances [flags]
* [cozy-stack instances refresh-token-oauth](cozy-stack_instances_refresh-token-oauth.md) - Generate a new OAuth refresh token
* [cozy-stack instances set-disk-quota](cozy-stack_instances_set-disk-quota.md) - Change the disk-quota of the instance
* [cozy-stack instances show](cozy-stack_instances_show.md) - Show the instance of the specified domain
+* [cozy-stack instances show-prefix](cozy-stack_instances_show-prefix.md) - Show the instance prefix of the specified domain
+* [cozy-stack instances show-swift-prefix](cozy-stack_instances_show-swift-prefix.md) - Show the instance swift prefix of the specified domain
* [cozy-stack instances token-app](cozy-stack_instances_token-app.md) - Generate a new application token
* [cozy-stack instances token-cli](cozy-stack_instances_token-cli.md) - Generate a new CLI access token (global access)
* [cozy-stack instances token-konnector](cozy-stack_instances_token-konnector.md) - Generate a new konnector token
diff --git a/docs/cli/cozy-stack_instances_client-oauth.md b/docs/cli/cozy-stack_instances_client-oauth.md
index ffbf6820645..d323fe65125 100644
--- a/docs/cli/cozy-stack_instances_client-oauth.md
+++ b/docs/cli/cozy-stack_instances_client-oauth.md
@@ -13,8 +13,9 @@ cozy-stack instances client-oauth [flags]
+```
+
+### Options
+
+```
+ -h, --help help for find-oauth-client
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack instances](cozy-stack_instances.md) - Manage instances of a stack
+
diff --git a/docs/cli/cozy-stack_instances_fsck.md b/docs/cli/cozy-stack_instances_fsck.md
index ed5bee7076d..fa0c3f07754 100644
--- a/docs/cli/cozy-stack_instances_fsck.md
+++ b/docs/cli/cozy-stack_instances_fsck.md
@@ -17,9 +17,9 @@ cozy-stack instances fsck [flags]
### Options
```
- --dry Don't modify the VFS, only show the inconsistencies
- -h, --help help for fsck
- --prune Try to solve inconsistencies by modifying the file system
+ -h, --help help for fsck
+ --index-indegrity Check the index integrity only
+ --json Output more informations in JSON format
```
### Options inherited from parent commands
diff --git a/docs/cli/cozy-stack_instances_insert-asset.md b/docs/cli/cozy-stack_instances_insert-asset.md
new file mode 100644
index 00000000000..5877509a5d6
--- /dev/null
+++ b/docs/cli/cozy-stack_instances_insert-asset.md
@@ -0,0 +1,42 @@
+## cozy-stack instances insert-asset
+
+Inserts an asset
+
+### Synopsis
+
+Inserts a custom asset in a specific context
+
+```
+cozy-stack instances insert-asset --url --name --shasum --context [flags]
+```
+
+### Examples
+
+```
+$ cozy-stack config insert-asset --url file:///foo/bar/baz.js --name /foo/bar/baz.js --shasum 0763d6c2cebee0880eb3a9cc25d38cd23db39b5c3802f2dc379e408c877a2788 --context foocontext
+```
+
+### Options
+
+```
+ --context string The context of the asset
+ -h, --help help for insert-asset
+ --name string The name of the asset
+ --shasum string The shasum of the asset
+ --url string The URL of the asset
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack instances](cozy-stack_instances.md) - Manage instances of a stack
+
diff --git a/docs/cli/cozy-stack_instances_ls.md b/docs/cli/cozy-stack_instances_ls.md
index 299e862b444..55a91883ed4 100644
--- a/docs/cli/cozy-stack_instances_ls.md
+++ b/docs/cli/cozy-stack_instances_ls.md
@@ -16,7 +16,9 @@ cozy-stack instances ls [flags]
### Options
```
- -h, --help help for ls
+ --fields strings Arguments shown for each line in the list
+ -h, --help help for ls
+ --json Show each line as a json representation of the instance
```
### Options inherited from parent commands
diff --git a/docs/cli/cozy-stack_instances_modify.md b/docs/cli/cozy-stack_instances_modify.md
index e28035e9137..eef2f3ac819 100644
--- a/docs/cli/cozy-stack_instances_modify.md
+++ b/docs/cli/cozy-stack_instances_modify.md
@@ -22,7 +22,7 @@ cozy-stack instances modify [flags]
--domain-aliases strings Specify one or more aliases domain for the instance (separated by ',')
--email string New email
-h, --help help for modify
- --locale string New locale (default "en")
+ --locale string New locale
--onboarding-finished Force the finishing of the onboarding
--public-name string New public name
--settings string New list of settings (eg offer:premium)
diff --git a/docs/cli/cozy-stack_instances_show-prefix.md b/docs/cli/cozy-stack_instances_show-prefix.md
new file mode 100644
index 00000000000..fe968d6a5e8
--- /dev/null
+++ b/docs/cli/cozy-stack_instances_show-prefix.md
@@ -0,0 +1,41 @@
+## cozy-stack instances show-prefix
+
+Show the instance prefix of the specified domain
+
+### Synopsis
+
+
+cozy-stack instances show allows to show the instance prefix on the cozy for a
+given domain. The prefix is used for databases and VFS prefixing.
+
+
+```
+cozy-stack instances show-prefix [flags]
+```
+
+### Examples
+
+```
+$ cozy-stack instances show-prefix cozy.tools:8080
+```
+
+### Options
+
+```
+ -h, --help help for show-prefix
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack instances](cozy-stack_instances.md) - Manage instances of a stack
+
diff --git a/docs/cli/cozy-stack_instances_show-swift-prefix.md b/docs/cli/cozy-stack_instances_show-swift-prefix.md
new file mode 100644
index 00000000000..c1fa36596e9
--- /dev/null
+++ b/docs/cli/cozy-stack_instances_show-swift-prefix.md
@@ -0,0 +1,38 @@
+## cozy-stack instances show-swift-prefix
+
+Show the instance swift prefix of the specified domain
+
+### Synopsis
+
+Show the instance swift prefix of the specified domain
+
+```
+cozy-stack instances show-swift-prefix [flags]
+```
+
+### Examples
+
+```
+$ cozy-stack instances show-swift-prefix cozy.tools:8080
+```
+
+### Options
+
+```
+ -h, --help help for show-swift-prefix
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack instances](cozy-stack_instances.md) - Manage instances of a stack
+
diff --git a/docs/cli/cozy-stack_swift.md b/docs/cli/cozy-stack_swift.md
new file mode 100644
index 00000000000..b3f3e0e014d
--- /dev/null
+++ b/docs/cli/cozy-stack_swift.md
@@ -0,0 +1,36 @@
+## cozy-stack swift
+
+Interact directly with OpenStack Swift object storage
+
+### Synopsis
+
+Interact directly with OpenStack Swift object storage
+
+```
+cozy-stack swift [flags]
+```
+
+### Options
+
+```
+ -h, --help help for swift
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack](cozy-stack.md) - cozy-stack is the main command
+* [cozy-stack swift get](cozy-stack_swift_get.md) -
+* [cozy-stack swift ls](cozy-stack_swift_ls.md) -
+* [cozy-stack swift put](cozy-stack_swift_put.md) -
+* [cozy-stack swift rm](cozy-stack_swift_rm.md) -
+
diff --git a/docs/cli/cozy-stack_swift_get.md b/docs/cli/cozy-stack_swift_get.md
new file mode 100644
index 00000000000..31204b8d14d
--- /dev/null
+++ b/docs/cli/cozy-stack_swift_get.md
@@ -0,0 +1,32 @@
+## cozy-stack swift get
+
+
+
+### Synopsis
+
+
+
+```
+cozy-stack swift get [flags]
+```
+
+### Options
+
+```
+ -h, --help help for get
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack swift](cozy-stack_swift.md) - Interact directly with OpenStack Swift object storage
+
diff --git a/docs/cli/cozy-stack_swift_ls.md b/docs/cli/cozy-stack_swift_ls.md
new file mode 100644
index 00000000000..62a1049ee0b
--- /dev/null
+++ b/docs/cli/cozy-stack_swift_ls.md
@@ -0,0 +1,32 @@
+## cozy-stack swift ls
+
+
+
+### Synopsis
+
+
+
+```
+cozy-stack swift ls [flags]
+```
+
+### Options
+
+```
+ -h, --help help for ls
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack swift](cozy-stack_swift.md) - Interact directly with OpenStack Swift object storage
+
diff --git a/docs/cli/cozy-stack_swift_put.md b/docs/cli/cozy-stack_swift_put.md
new file mode 100644
index 00000000000..05f95c0e765
--- /dev/null
+++ b/docs/cli/cozy-stack_swift_put.md
@@ -0,0 +1,35 @@
+## cozy-stack swift put
+
+
+
+### Synopsis
+
+cozy-stack swift put can be used to create or update an object in
+the swift container associated to the given domain. The content of the file is
+expected on the standard input.
+
+```
+cozy-stack swift put [flags]
+```
+
+### Options
+
+```
+ --content-type string Specify a Content-Type for the created object
+ -h, --help help for put
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack swift](cozy-stack_swift.md) - Interact directly with OpenStack Swift object storage
+
diff --git a/docs/cli/cozy-stack_swift_rm.md b/docs/cli/cozy-stack_swift_rm.md
new file mode 100644
index 00000000000..ba3a8d0285a
--- /dev/null
+++ b/docs/cli/cozy-stack_swift_rm.md
@@ -0,0 +1,32 @@
+## cozy-stack swift rm
+
+
+
+### Synopsis
+
+
+
+```
+cozy-stack swift rm [flags]
+```
+
+### Options
+
+```
+ -h, --help help for rm
+```
+
+### Options inherited from parent commands
+
+```
+ --admin-host string administration server host (default "localhost")
+ --admin-port int administration server port (default 6060)
+ -c, --config string configuration file (default "$HOME/.cozy.yaml")
+ --host string server host (default "localhost")
+ -p, --port int server port (default 8080)
+```
+
+### SEE ALSO
+
+* [cozy-stack swift](cozy-stack_swift.md) - Interact directly with OpenStack Swift object storage
+
diff --git a/docs/client-app-dev.md b/docs/client-app-dev.md
index 1100e9fb199..370607f04cc 100644
--- a/docs/client-app-dev.md
+++ b/docs/client-app-dev.md
@@ -23,10 +23,10 @@ The default passphrase will be "cozy"
To run the `scripts/cozy-app-dev.sh` directly on you system, you'll need to
following dependencies:
-* `go`
-* `curl`
-* `git`
-* `couchdb2`: you need at least a running instance of CouchDB 2
+- `go`
+- `curl`
+- `git`
+- `couchdb2`: you need at least a running instance of CouchDB 2
Examples:
@@ -53,6 +53,12 @@ $ ./scripts/cozy-app-dev.sh -h
If you do not want to install the required dependencies, we provide a Docker
image which encapsulates the dev script and all its dependencies.
+To download the latest version, you can run this command:
+
+```sh
+docker pull cozy/cozy-app-dev
+```
+
To run a ephemeral instance, on the `$HOME/myapp` directory, use the following
command (warning: all the data stored by your application in couchdb and the VFS
won't remain after):
@@ -119,8 +125,8 @@ When an application makes a request to the stack, like loading a list of
contacts, it sends two informations that will be used by the stack to allow or
deny the access:
-* the user session cookie
-* a token that identifies the application (only when the user is connected).
+- the user session cookie
+- a token that identifies the application (only when the user is connected).
So, the application needs such a token. It also needs to know where to send the
requests for the stack (it can be guessed, but with the nested vs flat
@@ -128,17 +134,17 @@ subdomains structures, it's better to get the information from the stack). To do
that, when the application loads its HTML index file, the stack will parse it as
a template and will insert the relevant values.
-* `{{.Token}}` will be replaced by the token for the application.
-* `{{.Domain}}` will be replaced by the stack hostname.
-* `{{.Locale}}` will be replaced by the locale for the instance.
-* `{{.AppName}}`: will be replaced by the application name.
-* `{{.AppSlug}}`: will be replaced by the application slug.
-* `{{.AppNamePrefix}}`: will be replaced by the application name prefix.
-* `{{.AppEditor}}`: will be replaced by the application's editor.
-* `{{.IconPath}}`: will be replaced by the application's icon path.
-* `{{.CozyBar}}` will be replaced by the JavaScript to inject the cozy-bar.
-* `{{.CozyClientJS}}` will be replaced by the JavaScript to inject the
- cozy-client-js.
+- `{{.Token}}` will be replaced by the token for the application.
+- `{{.Domain}}` will be replaced by the stack hostname.
+- `{{.Locale}}` will be replaced by the locale for the instance.
+- `{{.AppName}}`: will be replaced by the application name.
+- `{{.AppSlug}}`: will be replaced by the application slug.
+- `{{.AppNamePrefix}}`: will be replaced by the application name prefix.
+- `{{.AppEditor}}`: will be replaced by the application's editor.
+- `{{.IconPath}}`: will be replaced by the application's icon path.
+- `{{.CozyBar}}` will be replaced by the JavaScript to inject the cozy-bar.
+- `{{.CozyClientJS}}` will be replaced by the JavaScript to inject the
+ cozy-client-js.
So, the `index.html` should probably looks like:
@@ -167,11 +173,11 @@ And `my-app.js`:
"use strict";
document.addEventListener("DOMContentLoaded", () => {
- const app = document.querySelector("[role=application]");
- cozy.client.init({
- cozyURL: "//" + app.dataset.cozyStack,
- token: app.dataset.cozyToken
- });
+ const app = document.querySelector("[role=application]");
+ cozy.client.init({
+ cozyURL: "//" + app.dataset.cozyStack,
+ token: app.dataset.cozyToken
+ });
});
// ...
diff --git a/docs/config.md b/docs/config.md
index a2d993dc1a2..597fefc3f95 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -4,48 +4,48 @@
## Main Configuration file
-You can configure your `cozy-stack` using a configuration file. This file
-should be named `cozy.yaml` or `cozy.json` depending on the format of your
-chosing, and should be present in one of these directories (ordered by
-priority):
+You can configure your `cozy-stack` using a configuration file. This file should
+be named `cozy.yaml` or `cozy.json` depending on the format of your chosing, and
+should be present in one of these directories (ordered by priority):
-* `./.cozy`
-* `$HOME/.cozy`
-* `/etc/cozy`
+- `./.cozy`
+- `$HOME/.cozy`
+- `/etc/cozy`
The path of the configuration file can also be define from an absolute path
-given by the `--config` (or `-c`) flag of the [cozy-stack command](docs/cli
-/cozy-stack_serve.md).
+given by the `--config` (or `-c`) flag of the [cozy-stack command](./cli/cozy-stack_serve.md).
### Templating and Environment Variables
It is possible to pass environnment variable to this configuration using the
-[template language of golang](https://golang.org/pkg/text/template/),
-delimited by `{{` and `}}`.
+[template language of golang](https://golang.org/pkg/text/template/), delimited
+by `{{` and `}}`.
-The environment variables are available in the `.Env` variable. For instance
-the text `{{.Env.COUCHDB_PASSPHRASE }}` will be replaced by the value of the
-`COUCHDB_PASSPHRASE` environment variable. The template is evaluated at
-startup of the stack.
+The environment variables are available in the `.Env` variable. For instance the
+text `{{.Env.COUCHDB_PASSPHRASE }}` will be replaced by the value of the
+`COUCHDB_PASSPHRASE` environment variable. The template is evaluated at startup
+of the stack.
### Values and Example
-To see the detail of the available parameters available, you can see an
-example of configuration in the [cozy.example.yaml](../cozy.example.yaml) file
-at the root of this repository.
+To see the detail of the available parameters available, you can see an example
+of configuration in the [cozy.example.yaml](../cozy.example.yaml) file at the
+root of this repository.
-This file contains all the parameters and fields that can be used to configure the stack with some example values.
+This file contains all the parameters and fields that can be used to configure
+the stack with some example values.
-Some fields can be overriden by the flags of the [cozy-stack serve command](docs/cli/cozy-stack_serve.md).
+Some fields can be overriden by the flags of the
+[cozy-stack serve command](docs/cli/cozy-stack_serve.md).
## Stack endpoints
By default, `cozy-stack` use plain-text & local socket for client
(`localhost:8080`) and admin (`localhost:6060`) communications.
-If you want to control a remote stack or using TLS to secure communications,
-you can configure your `cozy-stack` client with the following CLI arguments
-or environment variables.
+If you want to control a remote stack or using TLS to secure communications, you
+can configure your `cozy-stack` client with the following CLI arguments or
+environment variables.
@@ -64,6 +64,7 @@ or environment variables.
`[http[s]://][:]`
+
@@ -89,7 +90,9 @@ Must be [a valid golang duration](https://golang.org/pkg/time/#ParseDuration) li
Enable HTTPS certificate validation
-Can also be set via host URL query part, like `https://localhost:6060?validate=false`
+Can also be set via host URL query part, like
+`https://localhost:6060?validate=false`
+
@@ -100,6 +103,7 @@ Can also be set via host URL query part, like `https://localhost:6060?validate=f
CA file to use for HTTPS certificate validation
Can also be set via host URL query part, like `https://localhost:6060?ca=`
+
@@ -109,7 +113,9 @@ Can also be set via host URL query part, like `https://localhost:6060?ca=`
Client certificate to use
-Can also be set via host URL query part, like `https://localhost:6060?cert=`
+Can also be set via host URL query part, like
+`https://localhost:6060?cert=`
+
@@ -120,6 +126,7 @@ Can also be set via host URL query part, like `https://localhost:6060?cert=`
+
@@ -135,6 +142,7 @@ You can get the fingerprint of a given certificate with
`openssl x509 -in -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -hex`
Or directly from a private key with
`openssl pkey -in -pubout -outform der | openssl dgst -sha256 -hex`
+
@@ -142,14 +150,15 @@ Or directly from a private key with
## Administration secret
-To access to the administration API (the `/admin/*` routes), a secret
-passphrase should be stored in a `cozy-admin-passphrase`. This file should be
-in one of the configuration directories, along with the main config file.
+To access to the administration API (the `/admin/*` routes), a secret passphrase
+should be stored in a `cozy-admin-passphrase`. This file should be in one of the
+configuration directories, along with the main config file.
The passphrase is stored in a salted-hashed representation using scrypt. To
-generate this file, you can use the `cozy-stack config passwd [config
-directory]` command. This command will ask you for a passphrase and will
-create the `cozy-admin-passphrase` in the specified directory.
+generate this file, you can use the
+`cozy-stack config passwd [config directory]` command. This command will ask you
+for a passphrase and will create the `cozy-admin-passphrase` in the specified
+directory.
You can use the `COZY_ADMIN_PASSWORD` env variable if you do not want to type
the passphrase each time you call `cozy-stack`.
@@ -167,13 +176,11 @@ cat ~/.cozy/cozy-admin-passphrase
Cozy-stack can run scripts on some events to customize it. The scripts must be
in the hooks directory defined in the config, have a predefined name, and be
-executable. Then, they should be fired automatically. Let's the available
-hooks.
+executable. Then, they should be fired automatically. Let's the available hooks.
The `pre-add-instance` hook is run just before creating an instance. It can
-prevent the command from running by exiting with non-zero status. It can be
-used to check the domain for example. It is called with the following
-parameter:
+prevent the command from running by exiting with non-zero status. It can be used
+to check the domain for example. It is called with the following parameter:
1. the domain of the instance that will be created.
@@ -183,10 +190,10 @@ called with the following parameter:
1. the domain of the instance that has been created.
-The `pre-remove-instance` hook is run just before destroying an instance. It
-can prevent the command from running by exiting with non-zero status. It can
-be used to make a backup of the instance before destroying it. It is called
-with the following parameter:
+The `pre-remove-instance` hook is run just before destroying an instance. It can
+prevent the command from running by exiting with non-zero status. It can be used
+to make a backup of the instance before destroying it. It is called with the
+following parameter:
1. the domain of the instance that will be destroyed.
@@ -196,32 +203,31 @@ parameter:
1. the domain of the instance that has been destroyed.
-The `pre-install-app` hook is run just before installing an application, and
-can prevent the command from running by exiting with non-zero status. It is
-called with the following parameters:
+The `pre-install-app` hook is run just before installing an application, and can
+prevent the command from running by exiting with non-zero status. It is called
+with the following parameters:
1. the instance on which the application will be installed
2. the application name that will be installed.
-The `post-install-app` hook is run just after an application has been
-installed. It can be used for logging, notification, statistics, etc. It's
-also a good place to add a vhost for an application in the reverse-proxy
-configuration, with a TLS certificate. It is called with the following
-parameters:
+The `post-install-app` hook is run just after an application has been installed.
+It can be used for logging, notification, statistics, etc. It's also a good
+place to add a vhost for an application in the reverse-proxy configuration, with
+a TLS certificate. It is called with the following parameters:
1. the instance on which the application has been installed
2. the application name that has been installed.
-The `pre-uninstall-app` hook is run just before uninstalling an application,
-and can prevent the command from running by exiting with non-zero status. It
-is called with the following parameters:
+The `pre-uninstall-app` hook is run just before uninstalling an application, and
+can prevent the command from running by exiting with non-zero status. It is
+called with the following parameters:
1. the instance on which the application will be uninstalled
2. the application name that will be uninstalled.
The `post-uninstall-app` hook is run just after an application has been
-uninstalled. It can be used for cleaning the configuration of the reverse-
-proxy for example. It is called with the following parameters:
+uninstalled. It can be used for cleaning the configuration of the reverse- proxy
+for example. It is called with the following parameters:
1. the instance on which the application has been uninstalled
2. the application name that has been uninstalled.
diff --git a/docs/couchdb-plugins.md b/docs/couchdb-plugins.md
index 720cf825965..aee2ae685bd 100644
--- a/docs/couchdb-plugins.md
+++ b/docs/couchdb-plugins.md
@@ -8,37 +8,37 @@
### https://github.com/timjacobi/go-couchdb
-* last edit 2016-08
-* Apparently one of the firsts
-* Includes a http module, trying to figure out why, might simply be history
- (started in 2014)
-* fork of the "original" https://github.com/fjl/go-couchdb
-* brother of https://github.com/pokstad/go-couchdb which is used in this cool
- article : http://pokstad.com/2015/04/18/couchdb-and-go.html
-* Have tools to run as couchdbapp / couchdbdaemon (we wont use these)
-* Allow to pass a net/http.RoundTripper for fine transport tunning.
-* Pr merged with some fix for couchdb2, not sure if there is more issue
+- last edit 2016-08
+- Apparently one of the firsts
+- Includes a http module, trying to figure out why, might simply be history
+ (started in 2014)
+- fork of the "original" https://github.com/fjl/go-couchdb
+- brother of https://github.com/pokstad/go-couchdb which is used in this cool
+ article : http://pokstad.com/2015/04/18/couchdb-and-go.html
+- Have tools to run as couchdbapp / couchdbdaemon (we wont use these)
+- Allow to pass a net/http.RoundTripper for fine transport tunning.
+- Pr merged with some fix for couchdb2, not sure if there is more issue
### https://github.com/zemirco/couchdb
-* last edit 2016-08
-* No functions for changes API
-* Have a special interface for document {GetID(), GetRev()}
+- last edit 2016-08
+- No functions for changes API
+- Have a special interface for document {GetID(), GetRev()}
### https://github.com/rhinoman/couchdb-go
-* last edit 2016-04
-* No functions for changes API
-* Have functions for managing users and roles
-* Have functions for proxying requests (downloads / uploads)
-* support json byte[] as well as interface{} for documents
-* Is clean and clear, but more complex because of more functions. We will need
- most those (users, proxy)
+- last edit 2016-04
+- No functions for changes API
+- Have functions for managing users and roles
+- Have functions for proxying requests (downloads / uploads)
+- support json byte[] as well as interface{} for documents
+- Is clean and clear, but more complex because of more functions. We will need
+ most those (users, proxy)
### https://github.com/dustin/go-couch
-* last edit 2016-08
-* Simplest
+- last edit 2016-08
+- Simplest
## Plan B - Make our own from net/http
@@ -47,55 +47,57 @@ packages for each function, some pitfalls could be avoided :
ex:
-* https://github.com/rhinoman/couchdb-go/blob/94e6ab663d5789615eb061b52ed2e67310bac13f/connection.go#L81
-* Use custom Director & httputil.ReverseProxy for file download / upload
+- https://github.com/rhinoman/couchdb-go/blob/94e6ab663d5789615eb061b52ed2e67310bac13f/connection.go#L81
+- Use custom Director & httputil.ReverseProxy for file download / upload
## Considerations on how we will use it
(see the [architecture](architecture.md) for more info)
-* One stack instance communicate with one couchdb 2.x server or cluster. The
- couchdb server/cluster has a lot of databases (nb_users x nb_data_types). The
- pair stack+couch should handle as many active users as possible. Number of
- unactive users must not impact perfs too much. Note : definition of active
- user TBD (mobile app and 3rd party software are syncing using \*dav and some
- background jobs like fetching banks accounts and threshold alerts )
-* HTTPS between stack and couchdb is not a priority. If it's an option, it will
- allow more flexibility for ops team, but we can always find alternative
- solution to secure channel between stack and couchdb and self-hosted users
- will probably have both on an single machine.
-* We wont keep changes feed open, as it was identified in couchdb workshop as
- the limiting factor on number of databases we can have and we want to have a
- bazillion databases. We will probably do some kind of polling, this will need
- to be investigated deeper.
-* Binaries will NOT be stored in couchdb. We will only store in couchdb
- reference to the file in another storage solution (FS / Swift)
-* The stack will use couchdb in 2 ways :
- 1. Just proxying to/from the client, we will still need to parse the JSON, but
- will only read or changes a few special fields (`_id`, `_type`, `_tags`
- ....) for ACL and then pipe it to/from couchdb. We wont need to make sense
- of the whole document and can eventually get away without parsing it on
- some routes. This part should be totally flexible on the json content.
- 2. Some APIs and Jobs will need to make sense of the given documents, so
- (un)marshal them from/into smarter struct (CalendarEvent) to be used in
- business logic.
+- One stack instance communicate with one couchdb 2.x server or cluster. The
+ couchdb server/cluster has a lot of databases (nb_users x nb_data_types).
+ The pair stack+couch should handle as many active users as possible. Number
+ of unactive users must not impact perfs too much. Note : definition of
+ active user TBD (mobile app and 3rd party software are syncing using \*dav
+ and some background jobs like fetching banks accounts and threshold alerts )
+- HTTPS between stack and couchdb is not a priority. If it's an option, it
+ will allow more flexibility for ops team, but we can always find alternative
+ solution to secure channel between stack and couchdb and self-hosted users
+ will probably have both on an single machine.
+- We wont keep changes feed open, as it was identified in couchdb workshop as
+ the limiting factor on number of databases we can have and we want to have a
+ bazillion databases. We will probably do some kind of polling, this will
+ need to be investigated deeper.
+- Binaries will NOT be stored in couchdb. We will only store in couchdb
+ reference to the file in another storage solution (FS / Swift)
+- The stack will use couchdb in 2 ways :
+ 1. Just proxying to/from the client, we will still need to parse the JSON,
+ but will only read or changes a few special fields (`_id`, `_type`,
+ `_tags` ....) for ACL and then pipe it to/from couchdb. We wont need to
+ make sense of the whole document and can eventually get away without
+ parsing it on some routes. This part should be totally flexible on the
+ json content.
+ 2. Some APIs and Jobs will need to make sense of the given documents, so
+ (un)marshal them from/into smarter struct (CalendarEvent) to be used in
+ business logic.
## Analysis
-* They are all relatively similar in term of API. rhinoman has some more
- functions that we will need but lack changes feed.
-* They all have a struct for database which hold configuration, as most of our
- request will be on different databases, we will have a great churn for these
- structure. This is less than optimal for RAM & GC, but probably insignificant
- against JSON parsing.
-* They all use JSON Marshal et encode to accept any interface{} as couchdb doc.
-* They are all relatively inactive / stable, not sure if it is because they are
- "finished" or abandonware.
-* No library has a notion of pooling connection. This is handled at the
- net/http.Transport level in golang.
-* Only the first library has option for fine-tunning of the internal
- Client/Transport,
-* No library support couchdb2 mango
+- They are all relatively similar in term of API. rhinoman has some more
+ functions that we will need but lack changes feed.
+- They all have a struct for database which hold configuration, as most of our
+ request will be on different databases, we will have a great churn for these
+ structure. This is less than optimal for RAM & GC, but probably
+ insignificant against JSON parsing.
+- They all use JSON Marshal et encode to accept any interface{} as couchdb
+ doc.
+- They are all relatively inactive / stable, not sure if it is because they
+ are "finished" or abandonware.
+- No library has a notion of pooling connection. This is handled at the
+ net/http.Transport level in golang.
+- Only the first library has option for fine-tunning of the internal
+ Client/Transport,
+- No library support couchdb2 mango
## Going further (thanks @tomquest)
@@ -130,16 +132,17 @@ credentials.
Pros:
-* Cozy-stack oriented (functionally)
-* Still able to access CouchDb natively (eg. `couchdb.Connection()`)
-* Can hide technical stuff: access to the pool, concurrency, caching, https,
- retries, timeouts...
-* Build and maintained by Cozy
+- Cozy-stack oriented (functionally)
+- Still able to access CouchDb natively (eg. `couchdb.Connection()`)
+- Can hide technical stuff: access to the pool, concurrency, caching, https,
+ retries, timeouts...
+- Build and maintained by Cozy
Cons:
-* DSL to write (and testing is a bit harder)
-* To be maintained, but in fact, this is already the case for the other wrappers
+- DSL to write (and testing is a bit harder)
+- To be maintained, but in fact, this is already the case for the other
+ wrappers
## Current decision
diff --git a/docs/couchdb-quirks.md b/docs/couchdb-quirks.md
index 0e99094e723..9d83be82895 100644
--- a/docs/couchdb-quirks.md
+++ b/docs/couchdb-quirks.md
@@ -4,11 +4,11 @@
### Exists operator
-The [`$exists`
-operator](http://docs.couchdb.org/en/stable/api/database/find.html#condition-operators)
+The
+[`$exists` operator](http://docs.couchdb.org/en/stable/api/database/find.html#condition-operators)
can be used with a mango index for the `true` value, but not for the `false`
-value. For `false`, a more heavy solution is required: [a partial
-index](http://docs.couchdb.org/en/stable/api/database/find.html#find-partial-indexes).
+value. For `false`, a more heavy solution is required:
+[a partial index](http://docs.couchdb.org/en/stable/api/database/find.html#find-partial-indexes).
### Index selection
@@ -23,49 +23,51 @@ reasons. In general, you can follow these two rules of thumb:
fields, you can just add two filters `$exists: true` (one for `bar`, the
other for `baz`).
-2. You should use exactly the same sequence of fields for creating the index
- and the `sort` operator of the query. If you have an index on `os, browser, ip` for the `io.cozy.sessions.logins`, and you want to have all the
- documents for a login from `windows`, sorted by `browser`, you can use the
- index, but you should use `os, browser, ip` for the sort (or at least `os, browser`, even if it is seems to weird to sort on `os` when all the sorted
- documents will have the same value, `windows`). Please note that using
- `use_index` on a request, the results will be sorted by default according
- to this rule. So, you can omit the `sort` operator on the query (except if
- you want the `descending` order).
+2. You should use exactly the same sequence of fields for creating the index and
+ the `sort` operator of the query. If you have an index on `os, browser, ip`
+ for the `io.cozy.sessions.logins`, and you want to have all the documents for
+ a login from `windows`, sorted by `browser`, you can use the index, but you
+ should use `os, browser, ip` for the sort (or at least `os, browser`, even if
+ it is seems to weird to sort on `os` when all the sorted documents will have
+ the same value, `windows`). Please note that using `use_index` on a request,
+ the results will be sorted by default according to this rule. So, you can
+ omit the `sort` operator on the query (except if you want the `descending`
+ order).
## Old revisions
CouchDB keeps for each document a list of its revision (or more exactly a tree
with replication and conflicts).
-It's possible to ask the list of the old revisions of a document with [`GET /db/{docid}?revs_info=true`](http://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid).
-It works only if the document has not been deleted. For a deleted document, [a
-trick](https://stackoverflow.com/questions/10854883/retrieve-just-deleted-document/10857330#10857330)
+It's possible to ask the list of the old revisions of a document with
+[`GET /db/{docid}?revs_info=true`](http://docs.couchdb.org/en/stable/api/document/common.html#get--db-docid).
+It works only if the document has not been deleted. For a deleted document,
+[a trick](https://stackoverflow.com/questions/10854883/retrieve-just-deleted-document/10857330#10857330)
is to query the changes feed to know the last revision of the document, and to
recreate the document from this revision.
With an old revision, it's possible to get the content of the document at this
-revision with `GET /db/{docid}?rev={rev}` if the database was not compacted.
-On CouchDB 2.x, compacts happen automatically on all databases from times to
-times.
+revision with `GET /db/{docid}?rev={rev}` if the database was not compacted. On
+CouchDB 2.x, compacts happen automatically on all databases from times to times.
-A `purge` operation consists to remove the tombstone for the deleted
-documents. It is a manual operation, triggered by a
+A `purge` operation consists to remove the tombstone for the deleted documents.
+It is a manual operation, triggered by a
[`POST /db/_purge`](http://docs.couchdb.org/en/stable/api/database/misc.html).
## Conflicts
-It is possible to create a conflict on CouchDB like it does for the
-replication by using `new_edits`, but it is not well documented to say the
-least. The more accurate description is on the old wiki:
+It is possible to create a conflict on CouchDB like it does for the replication
+by using `new_edits`, but it is not well documented to say the least. The more
+accurate description is on the old wiki:
https://wiki.apache.org/couchdb/HTTP_Bulk_Document_API#Posting_Existing_Revisions.
-In short, it's a `PUT /doc/{id}?new_edits=false` with `_rev` the new revision
-of the document, and `_revisions` the parents of this revision in the
-revisions tree of this document.
+In short, it's a `PUT /doc/{id}?new_edits=false` with `_rev` the new revision of
+the document, and `_revisions` the parents of this revision in the revisions
+tree of this document.
## Design docs in \_all_docs
When querying `GET /{db}/_all_docs`, the response include the design docs. It's
-quite difficult to filter them, particulary when pagination is involved. We
-have added an endpoint `GET /data/:doctype/_normal_docs` to the stack to help
-client side applications to deal with this.
+quite difficult to filter them, particulary when pagination is involved. We have
+added an endpoint `GET /data/:doctype/_normal_docs` to the stack to help client
+side applications to deal with this.
diff --git a/docs/data-system.md b/docs/data-system.md
index 236c75e5001..082519e23d9 100644
--- a/docs/data-system.md
+++ b/docs/data-system.md
@@ -40,13 +40,13 @@ Etag: "3-6494e0ac6494e0ac"
```json
{
- "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "_type": "io.cozy.events",
- "_rev": "3-6494e0ac6494e0ac",
- "startdate": "20160823T150000Z",
- "enddate": "20160923T160000Z",
- "summary": "A long month",
- "description": "I could go on and on and on ...."
+ "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "_type": "io.cozy.events",
+ "_rev": "3-6494e0ac6494e0ac",
+ "startdate": "20160823T150000Z",
+ "enddate": "20160923T160000Z",
+ "summary": "A long month",
+ "description": "I could go on and on and on ...."
}
```
@@ -60,24 +60,24 @@ Content-Type: application/json
```json
{
- "status": 404,
- "error": "not_found",
- "reason": "deleted",
- "title": "Event deleted",
- "details": "Event 6494e0ac-dfcb-11e5-88c1-472e84a9cbee was deleted",
- "links": { "about": "https://cozy.github.io/cozy-stack/errors.md#deleted" }
+ "status": 404,
+ "error": "not_found",
+ "reason": "deleted",
+ "title": "Event deleted",
+ "details": "Event 6494e0ac-dfcb-11e5-88c1-472e84a9cbee was deleted",
+ "links": { "about": "https://cozy.github.io/cozy-stack/errors.md#deleted" }
}
```
### possible errors :
-* 401 unauthorized (no authentication has been provided)
-* 403 forbidden (the authentication does not provide permissions for this
- action)
-* 404 not_found
- * reason: missing
- * reason: deleted
-* 500 internal server error
+- 401 unauthorized (no authentication has been provided)
+- 403 forbidden (the authentication does not provide permissions for this
+ action)
+- 404 not_found
+ - reason: missing
+ - reason: deleted
+- 500 internal server error
## Access multiple documents at once
@@ -96,10 +96,10 @@ Accept: application/json
```json
{
- "keys": [
- "7f46ed4ed2a775494da3b0b44e00314f",
- "7f46ed4ed2a775494da3b0b44e003b18"
- ]
+ "keys": [
+ "7f46ed4ed2a775494da3b0b44e00314f",
+ "7f46ed4ed2a775494da3b0b44e003b18"
+ ]
}
```
@@ -115,40 +115,40 @@ Etag: "3-6494e0ac6494e0ac"
```json
{
- "total_rows": 11,
- "rows": [
- {
- "id": "7f46ed4ed2a775494da3b0b44e00314f",
- "key": "7f46ed4ed2a775494da3b0b44e00314f",
- "value": {
- "rev": "1-870e58f8a1b2130c3a41e767f9c7d93a"
- },
- "doc": {
- "_id": "7f46ed4ed2a775494da3b0b44e00314f",
- "_rev": "1-870e58f8a1b2130c3a41e767f9c7d93a",
- "type": "directory",
- "name": "Uploaded from Cozy Photos",
- "dir_id": "7f46ed4ed2a775494da3b0b44e0027df",
- "created_at": "2017-07-04T06:49:12.844631837Z",
- "updated_at": "2017-07-04T06:49:12.844631837Z",
- "tags": [],
- "path": "/Photos/Uploaded from Cozy Photos"
- }
- },
- {
- "key": "7f46ed4ed2a775494da3b0b44e003b18",
- "error": "not_found"
- }
- ]
+ "total_rows": 11,
+ "rows": [
+ {
+ "id": "7f46ed4ed2a775494da3b0b44e00314f",
+ "key": "7f46ed4ed2a775494da3b0b44e00314f",
+ "value": {
+ "rev": "1-870e58f8a1b2130c3a41e767f9c7d93a"
+ },
+ "doc": {
+ "_id": "7f46ed4ed2a775494da3b0b44e00314f",
+ "_rev": "1-870e58f8a1b2130c3a41e767f9c7d93a",
+ "type": "directory",
+ "name": "Uploaded from Cozy Photos",
+ "dir_id": "7f46ed4ed2a775494da3b0b44e0027df",
+ "created_at": "2017-07-04T06:49:12.844631837Z",
+ "updated_at": "2017-07-04T06:49:12.844631837Z",
+ "tags": [],
+ "path": "/Photos/Uploaded from Cozy Photos"
+ }
+ },
+ {
+ "key": "7f46ed4ed2a775494da3b0b44e003b18",
+ "error": "not_found"
+ }
+ ]
}
```
### possible errors :
-* 401 unauthorized (no authentication has been provided)
-* 403 forbidden (the authentication does not provide permissions for this
- action)
-* 500 internal server error
+- 401 unauthorized (no authentication has been provided)
+- 403 forbidden (the authentication does not provide permissions for this
+ action)
+- 500 internal server error
### Details
@@ -173,8 +173,8 @@ Accept: application/json
```json
{
- "startdate": "20160712T150000",
- "enddate": "20160712T150000"
+ "startdate": "20160712T150000",
+ "enddate": "20160712T150000"
}
```
@@ -188,33 +188,33 @@ Content-Type: application/json
```json
{
- "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "type": "io.cozy.events",
- "ok": true,
- "rev": "1-6494e0ac6494e0ac",
- "data": {
- "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "_type": "io.cozy.events",
- "_rev": "1-6494e0ac6494e0ac",
- "startdate": "20160712T150000",
- "enddate": "20160712T150000"
- }
+ "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "type": "io.cozy.events",
+ "ok": true,
+ "rev": "1-6494e0ac6494e0ac",
+ "data": {
+ "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "_type": "io.cozy.events",
+ "_rev": "1-6494e0ac6494e0ac",
+ "startdate": "20160712T150000",
+ "enddate": "20160712T150000"
+ }
}
```
### possible errors :
-* 400 bad request
-* 401 unauthorized (no authentication has been provided)
-* 403 forbidden (the authentication does not provide permissions for this
- action)
-* 500 internal server error
+- 400 bad request
+- 401 unauthorized (no authentication has been provided)
+- 403 forbidden (the authentication does not provide permissions for this
+ action)
+- 500 internal server error
### Details
-* A doc cannot contain an `_id` field, if so an error 400 is returned
-* A doc cannot contain any field starting with `_`, those are reserved for
- future cozy & couchdb api evolution
+- A doc cannot contain an `_id` field, if so an error 400 is returned
+- A doc cannot contain any field starting with `_`, those are reserved for
+ future cozy & couchdb api evolution
## Update an existing document
@@ -233,11 +233,11 @@ Accept: application/json
```json
{
- "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "_type": "io.cozy.events",
- "_rev": "1-6494e0ac6494e0ac",
- "startdate": "20160712T150000",
- "enddate": "20160712T200000"
+ "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "_type": "io.cozy.events",
+ "_rev": "1-6494e0ac6494e0ac",
+ "startdate": "20160712T150000",
+ "enddate": "20160712T200000"
}
```
@@ -251,31 +251,31 @@ Content-Type: application/json
```json
{
- "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "type": "io.cozy.events",
- "ok": true,
- "rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
- "data": {
- "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "_type": "io.cozy.events",
- "_rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
- "startdate": "20160712T150000",
- "enddate": "20160712T200000"
- }
+ "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "type": "io.cozy.events",
+ "ok": true,
+ "rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
+ "data": {
+ "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "_type": "io.cozy.events",
+ "_rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
+ "startdate": "20160712T150000",
+ "enddate": "20160712T200000"
+ }
}
```
### Possible errors :
-* 400 bad request
-* 401 unauthorized (no authentication has been provided)
-* 403 forbidden (the authentication does not provide permissions for this
- action)
-* 404 not_found
- * reason: missing
- * reason: deleted
-* 409 Conflict (see Conflict prevention section below)
-* 500 internal server error
+- 400 bad request
+- 401 unauthorized (no authentication has been provided)
+- 403 forbidden (the authentication does not provide permissions for this
+ action)
+- 404 not_found
+ - reason: missing
+ - reason: deleted
+- 409 Conflict (see Conflict prevention section below)
+- 500 internal server error
### Conflict prevention
@@ -285,9 +285,9 @@ be returned.
### Details
-* If no id is provided in URL, an error 400 is returned
-* If the id provided in URL is not the same than the one in document, an error
- 400 is returned.
+- If no id is provided in URL, an error 400 is returned
+- If the id provided in URL is not the same than the one in document, an error
+ 400 is returned.
## Create a document with a fixed id
@@ -306,8 +306,8 @@ Accept: application/json
```json
{
- "startdate": "20160712T150000",
- "enddate": "20160712T200000"
+ "startdate": "20160712T150000",
+ "enddate": "20160712T200000"
}
```
@@ -321,35 +321,35 @@ Content-Type: application/json
```json
{
- "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "type": "io.cozy.events",
- "ok": true,
- "rev": "1-056f5f44046ecafc08a2bc2b9c229e20",
- "data": {
- "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "_type": "io.cozy.events",
- "_rev": "1-056f5f44046ecafc08a2bc2b9c229e20",
- "startdate": "20160712T150000",
- "enddate": "20160712T200000"
- }
+ "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "type": "io.cozy.events",
+ "ok": true,
+ "rev": "1-056f5f44046ecafc08a2bc2b9c229e20",
+ "data": {
+ "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "_type": "io.cozy.events",
+ "_rev": "1-056f5f44046ecafc08a2bc2b9c229e20",
+ "startdate": "20160712T150000",
+ "enddate": "20160712T200000"
+ }
}
```
### Possible errors :
-* 400 bad request
-* 401 unauthorized (no authentication has been provided)
-* 403 forbidden (the authentication does not provide permissions for this
- action)
-* 404 not_found
- * reason: missing
- * reason: deleted
-* 409 Conflict (see Conflict prevention section below)
-* 500 internal server error
+- 400 bad request
+- 401 unauthorized (no authentication has been provided)
+- 403 forbidden (the authentication does not provide permissions for this
+ action)
+- 404 not_found
+ - reason: missing
+ - reason: deleted
+- 409 Conflict (see Conflict prevention section below)
+- 500 internal server error
### Details
-* No id should be provide in the document itself
+- No id should be provide in the document itself
## Delete a document
@@ -374,38 +374,38 @@ Content-Type: application/json
```json
{
- "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "type": "io.cozy.events",
- "ok": true,
- "rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
- "_deleted": true
+ "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "type": "io.cozy.events",
+ "ok": true,
+ "rev": "2-056f5f44046ecafc08a2bc2b9c229e20",
+ "_deleted": true
}
```
### Possible errors :
-* 400 bad request
-* 401 unauthorized (no authentication has been provided)
-* 403 forbidden (the authentication does not provide permissions for this
- action)
-* 404 not_found
- * reason: missing
- * reason: deleted
-* 409 Conflict (see Conflict prevention section below)
-* 500 internal server error
+- 400 bad request
+- 401 unauthorized (no authentication has been provided)
+- 403 forbidden (the authentication does not provide permissions for this
+ action)
+- 404 not_found
+ - reason: missing
+ - reason: deleted
+- 409 Conflict (see Conflict prevention section below)
+- 500 internal server error
### Conflict prevention
It is possible to use either a `rev` query string parameter or a HTTP `If-Match`
header to prevent conflict on deletion:
-* If none is passed or they are different, an error 400 is returned
-* If only one is passed or they are equals, the document will only be deleted if
- its `_rev` match the passed one. Otherwise, an error 409 is returned.
+- If none is passed or they are different, an error 400 is returned
+- If only one is passed or they are equals, the document will only be deleted
+ if its `_rev` match the passed one. Otherwise, an error 409 is returned.
### Details
-* If no id is provided in URL, an error 400 is returned
+- If no id is provided in URL, an error 400 is returned
## List all the documents
@@ -425,30 +425,30 @@ Content-Type: application/json
```json
{
- "offset": 0,
- "rows": [
- {
- "id": "16e458537602f5ef2a710089dffd9453",
- "key": "16e458537602f5ef2a710089dffd9453",
- "value": {
- "rev": "1-967a00dff5e02add41819138abb3284d"
- },
- "doc": {
- "field": "value"
- }
- },
- {
- "id": "f4ca7773ddea715afebc4b4b15d4f0b3",
- "key": "f4ca7773ddea715afebc4b4b15d4f0b3",
- "value": {
- "rev": "2-7051cbe5c8faecd085a3fa619e6e6337"
- },
- "doc": {
- "field": "other-value"
- }
- }
- ],
- "total_rows": 2
+ "offset": 0,
+ "rows": [
+ {
+ "id": "16e458537602f5ef2a710089dffd9453",
+ "key": "16e458537602f5ef2a710089dffd9453",
+ "value": {
+ "rev": "1-967a00dff5e02add41819138abb3284d"
+ },
+ "doc": {
+ "field": "value"
+ }
+ },
+ {
+ "id": "f4ca7773ddea715afebc4b4b15d4f0b3",
+ "key": "f4ca7773ddea715afebc4b4b15d4f0b3",
+ "value": {
+ "rev": "2-7051cbe5c8faecd085a3fa619e6e6337"
+ },
+ "doc": {
+ "field": "other-value"
+ }
+ }
+ ],
+ "total_rows": 2
}
```
@@ -459,10 +459,10 @@ See
## List all the documents (alternative)
-The `_all_docs` endpoint sends the design docs in the response. It makes it
-hard to use pagination on it. We have added a non-standard `_normal_docs`
-endpoint. This new endpoint skip the design docs (and does not count them in
-the `total_rows`). It only accepts two parameters in the query string: `skip`
+The `_all_docs` endpoint sends the design docs in the response. It makes it hard
+to use pagination on it. We have added a non-standard `_normal_docs` endpoint.
+This new endpoint skip the design docs (and does not count them in the
+`total_rows`). It only accepts two parameters in the query string: `skip`
(default: 0) and `limit` (default: 100).
Note that the response format is a bit different, it looks more like a `_find`
@@ -484,19 +484,19 @@ Content-Type: application/json
```json
{
- "rows": [
- {
- "_id": "16e458537602f5ef2a710089dffd9453",
- "_rev": "1-967a00dff5e02add41819138abb3284d",
- "field": "value"
- },
- {
- "_id": "f4ca7773ddea715afebc4b4b15d4f0b3",
- "_rev": "2-7051cbe5c8faecd085a3fa619e6e6337",
- "field": "other-value"
- }
- ],
- "total_rows": 202
+ "rows": [
+ {
+ "_id": "16e458537602f5ef2a710089dffd9453",
+ "_rev": "1-967a00dff5e02add41819138abb3284d",
+ "field": "value"
+ },
+ {
+ "_id": "f4ca7773ddea715afebc4b4b15d4f0b3",
+ "_rev": "2-7051cbe5c8faecd085a3fa619e6e6337",
+ "field": "other-value"
+ }
+ ],
+ "total_rows": 202
}
```
@@ -522,6 +522,6 @@ Content-Type: application/json
## Others
-* The creation and usage of [Mango indexes](mango.md) is possible.
-* CouchDB behaviors are not always straight forward: see [some
- quirks](couchdb-quirks.md) for more details.
+- The creation and usage of [Mango indexes](mango.md) is possible.
+- CouchDB behaviors are not always straight forward: see
+ [some quirks](couchdb-quirks.md) for more details.
diff --git a/docs/diagrams/konnector-models.dot b/docs/diagrams/konnector-models.dot
new file mode 100644
index 00000000000..5faa5a55a77
--- /dev/null
+++ b/docs/diagrams/konnector-models.dot
@@ -0,0 +1,20 @@
+digraph konnectors {
+ graph [rankdir="LR", splines=true];
+ node [fontname="roboto"];
+
+ trigger [label="Trigger | _id: [id] | worker: konnector | type: @cron | arguments: 0 31 0 * * 1 | { message | { folder_to_save: [id] | account: [id] | konnector: [slug] }}", shape="record"];
+ permissions [label="Permission | id: [id] | source_id: [id] |{ permissions | { saveFolder: [id] | ... }}", shape="record"];
+ konnector [label="Konnector | _id: io.cozy.konnectors/[slug] | slug: [slug] | ...", shape="record"];
+ account [label="Account | _id: [id] | { auth | { login: [string] | password: [string ]}} | data: [object] | folderPath: [string] | namePath: [string] | account_type: [slug] | label: [string]", shape="record"];
+ folder [label="Folder | _id: [id] | type: directory | path: [string] | name: [string] | {referenced_by: |[ [type] [id]}", shape="record"];
+
+ trigger:k_slug -> konnector:slug;
+ trigger:a_id -> account:id;
+ trigger:f_id -> folder:id;
+ konnector:id -> permissions:source_id;
+ permissions:f_id -> folder:id;
+ account:k_slug -> konnector:slug;
+ account:f_path -> folder:path;
+ account:f_name -> folder:name;
+ folder:ref -> konnector:id;
+}
diff --git a/docs/diagrams/konnector-models.png b/docs/diagrams/konnector-models.png
new file mode 100644
index 00000000000..fa3a69791ac
Binary files /dev/null and b/docs/diagrams/konnector-models.png differ
diff --git a/docs/diagrams/konnector-workflow.mmdc b/docs/diagrams/konnector-workflow.mmdc
new file mode 100644
index 00000000000..00251667f41
--- /dev/null
+++ b/docs/diagrams/konnector-workflow.mmdc
@@ -0,0 +1,22 @@
+sequenceDiagram
+ %% https://mermaidjs.github.io/
+ participant H as Home
+ participant C as Cozy-Stack
+ participant K as Konnector
+ participant S as External service
+
+ H ->> C: create folder
+ H ->> C: create a reference folder->konnector
+ H ->> C: create the account
+ H ->> C: create the trigger
+ H ->> C: launch the konnector
+
+ C ->> C: Ensure the konnector can write files
+ C ->> K: start the konnector
+ K ->> C: fetch the account
+ K ->> S: login
+ K -->> C: [log] login successful
+ C -->> H: [ws] login successful
+ K ->> S: fetch data
+ K ->> C: save documents and files
+ C -->>H: [ws] success / error
diff --git a/docs/diagrams/konnector-workflow.png b/docs/diagrams/konnector-workflow.png
new file mode 100644
index 00000000000..e7da9555cce
Binary files /dev/null and b/docs/diagrams/konnector-workflow.png differ
diff --git a/docs/docker.md b/docs/docker.md
index 8723ad59cfd..b1201c0c5ff 100644
--- a/docs/docker.md
+++ b/docs/docker.md
@@ -37,7 +37,5 @@ docker run -it --rm --name cozy-stack \
## Publishing a new cozy-app-dev image
-```bash
-./scripts/build.sh docker-dev
-docker push cozy/cozy-app-dev
-```
+We publish the cozy-app-dev image when we release a new version of the stack.
+See `scripts/release.sh` for details.
diff --git a/docs/files.md b/docs/files.md
index 0d08558a133..df432d123b4 100644
--- a/docs/files.md
+++ b/docs/files.md
@@ -51,12 +51,13 @@ Date: Mon, 19 Sep 2016 12:35:08 GMT
#### Status codes
-* 201 Created, when the directory has been successfully created
-* 404 Not Found, when the parent directory does not exist
-* 409 Conflict, when a directory with the same name already exists
-* 413 Payload Too Large, when there is not enough available space on the cozy to upload the file
-* 422 Unprocessable Entity, when the `Type` or `Name` parameter is missing or
- invalid
+- 201 Created, when the directory has been successfully created
+- 404 Not Found, when the parent directory does not exist
+- 409 Conflict, when a directory with the same name already exists
+- 413 Payload Too Large, when there is not enough available space on the cozy
+ to upload the file
+- 422 Unprocessable Entity, when the `Type` or `Name` parameter is missing or
+ invalid
#### Response
@@ -68,35 +69,35 @@ Location: http://cozy.example.com/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee
```json
{
- "data": {
- "type": "io.cozy.files",
- "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "meta": {
- "rev": "1-ff3beeb456eb"
- },
- "attributes": {
- "type": "directory",
- "name": "phone",
- "path": "/Documents/phone",
- "created_at": "2016-09-19T12:35:08Z",
- "updated_at": "2016-09-19T12:35:08Z",
- "tags": ["bills"]
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "data": {
+ "type": "io.cozy.files",
+ "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "meta": {
+ "rev": "1-ff3beeb456eb"
+ },
+ "attributes": {
+ "type": "directory",
+ "name": "phone",
+ "path": "/Documents/phone",
+ "created_at": "2016-09-19T12:35:08Z",
+ "updated_at": "2016-09-19T12:35:08Z",
+ "tags": ["bills"]
+ },
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ }
+ }
},
- "data": {
- "type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "links": {
+ "self": "/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee"
}
- }
- },
- "links": {
- "self": "/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee"
}
- }
}
```
@@ -124,107 +125,106 @@ Content-Type: application/vnd.api+json
```json
{
- "links": {
- "next":
- "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81?page[cursor]=9152d568-7e7c-11e6-a377-37cbfb190b4b"
- },
- "data": {
- "type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81",
- "meta": {
- "rev": "1-e36ab092"
- },
- "attributes": {
- "type": "directory",
- "name": "Documents",
- "path": "/Documents",
- "created_at": "2016-09-19T12:35:00Z",
- "updated_at": "2016-09-19T12:35:00Z",
- "tags": []
- },
- "relationships": {
- "contents": {
- "data": [
- {
- "type": "io.cozy.files",
- "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee"
- },
- {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b"
- }
- ]
- }
- },
"links": {
- "self": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
- }
- },
- "included": [
- {
- "type": "io.cozy.files",
- "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "meta": {
- "rev": "1-ff3beeb456eb"
- },
- "attributes": {
- "type": "directory",
- "name": "phone",
- "path": "/Documents/phone",
- "created_at": "2016-09-19T12:35:08Z",
- "updated_at": "2016-09-19T12:35:08Z",
- "tags": ["bills"]
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
- },
- "data": {
- "type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
- }
+ "next": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81?page[cursor]=9152d568-7e7c-11e6-a377-37cbfb190b4b"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81",
+ "meta": {
+ "rev": "1-e36ab092"
+ },
+ "attributes": {
+ "type": "directory",
+ "name": "Documents",
+ "path": "/Documents",
+ "created_at": "2016-09-19T12:35:00Z",
+ "updated_at": "2016-09-19T12:35:00Z",
+ "tags": []
+ },
+ "relationships": {
+ "contents": {
+ "data": [
+ {
+ "type": "io.cozy.files",
+ "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b"
+ }
+ ]
+ }
+ },
+ "links": {
+ "self": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
}
- },
- "links": {
- "self": "/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee"
- }
},
- {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "meta": {
- "rev": "1-0e6d5b72"
- },
- "attributes": {
- "type": "file",
- "name": "hello.txt",
- "trashed": false,
- "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": [],
- "size": 12,
- "executable": false,
- "class": "document",
- "mime": "text/plain"
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
- },
- "data": {
+ "included": [
+ {
+ "type": "io.cozy.files",
+ "id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "meta": {
+ "rev": "1-ff3beeb456eb"
+ },
+ "attributes": {
+ "type": "directory",
+ "name": "phone",
+ "path": "/Documents/phone",
+ "created_at": "2016-09-19T12:35:08Z",
+ "updated_at": "2016-09-19T12:35:08Z",
+ "tags": ["bills"]
+ },
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ }
+ }
+ },
+ "links": {
+ "self": "/files/6494e0ac-dfcb-11e5-88c1-472e84a9cbee"
+ }
+ },
+ {
"type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
- }
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "meta": {
+ "rev": "1-0e6d5b72"
+ },
+ "attributes": {
+ "type": "file",
+ "name": "hello.txt",
+ "trashed": false,
+ "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": [],
+ "size": 12,
+ "executable": false,
+ "class": "document",
+ "mime": "text/plain"
+ },
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ }
+ }
+ },
+ "links": {
+ "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
+ }
}
- },
- "links": {
- "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
- }
- }
- ]
+ ]
}
```
@@ -278,13 +278,14 @@ Hello world!
#### Status codes
-* 201 Created, when the file has been successfully created
-* 404 Not Found, when the parent directory does not exist
-* 409 Conflict, when a file with the same name already exists
-* 412 Precondition Failed, when the md5sum is `Content-MD5` is not equal to the
- md5sum computed by the server
-* 422 Unprocessable Entity, when the sent data is invalid (for example, the
- parent doesn't exist, `Type` or `Name` parameter is missing or invalid, etc.)
+- 201 Created, when the file has been successfully created
+- 404 Not Found, when the parent directory does not exist
+- 409 Conflict, when a file with the same name already exists
+- 412 Precondition Failed, when the md5sum is `Content-MD5` is not equal to
+ the md5sum computed by the server
+- 422 Unprocessable Entity, when the sent data is invalid (for example, the
+ parent doesn't exist, `Type` or `Name` parameter is missing or invalid,
+ etc.)
#### Response
@@ -296,63 +297,59 @@ Location: http://cozy.example.com/files/9152d568-7e7c-11e6-a377-37cbfb190b4b
```json
{
- "data": {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "meta": {
- "rev": "1-0e6d5b72"
- },
- "attributes": {
- "type": "file",
- "name": "sunset.jpg",
- "trashed": false,
- "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": [],
- "metadata": {
- "datetime": "2016-09-18T20:38:04Z",
- "height": 1080,
- "width": 1920
- },
- "size": 12,
- "executable": false,
- "class": "image",
- "mime": "image/jpg"
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "data": {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "meta": {
+ "rev": "1-0e6d5b72"
},
- "data": {
- "type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
- }
- },
- "referenced_by": {
- "links": {
- "self":
- "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81/relationships/references"
+ "attributes": {
+ "type": "file",
+ "name": "sunset.jpg",
+ "trashed": false,
+ "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": [],
+ "metadata": {
+ "datetime": "2016-09-18T20:38:04Z",
+ "height": 1080,
+ "width": 1920
+ },
+ "size": 12,
+ "executable": false,
+ "class": "image",
+ "mime": "image/jpg"
},
- "data": [
- {
- "type": "io.cozy.albums",
- "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
- }
- ]
- }
- },
- "links": {
- "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "small":
- "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/small",
- "medium":
- "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/medium",
- "large":
- "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/large"
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ }
+ },
+ "referenced_by": {
+ "links": {
+ "self": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81/relationships/references"
+ },
+ "data": [
+ {
+ "type": "io.cozy.albums",
+ "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
+ }
+ ]
+ }
+ },
+ "links": {
+ "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "small": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/small",
+ "medium": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/medium",
+ "large": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b/thumbnails/0f9cda56674282ac/large"
+ }
}
- }
}
```
@@ -426,10 +423,10 @@ HELLO WORLD!
#### Status codes
-* 200 OK, when the file has been successfully overwritten
-* 404 Not Found, when the file wasn't existing
-* 412 Precondition Failed, when the `If-Match` header is set and doesn't match
- the last revision of the file
+- 200 OK, when the file has been successfully overwritten
+- 404 Not Found, when the file wasn't existing
+- 412 Precondition Failed, when the `If-Match` header is set and doesn't match
+ the last revision of the file
#### Response
@@ -440,40 +437,40 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "meta": {
- "rev": "2-d903b54c"
- },
- "attributes": {
- "type": "file",
- "name": "hello.txt",
- "trashed": false,
- "md5sum": "YjU5YmMzN2Q2NDQxZDk2Nwo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": [],
- "size": 12,
- "executable": false,
- "class": "document",
- "mime": "text/plain"
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "data": {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "meta": {
+ "rev": "2-d903b54c"
+ },
+ "attributes": {
+ "type": "file",
+ "name": "hello.txt",
+ "trashed": false,
+ "md5sum": "YjU5YmMzN2Q2NDQxZDk2Nwo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": [],
+ "size": 12,
+ "executable": false,
+ "class": "document",
+ "mime": "text/plain"
+ },
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ }
+ }
},
- "data": {
- "type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "links": {
+ "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
}
- }
- },
- "links": {
- "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
}
- }
}
```
@@ -503,40 +500,40 @@ Location: http://cozy.example.com/files/9152d568-7e7c-11e6-a377-37cbfb190b4b
```json
{
- "data": {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "meta": {
- "rev": "1-0e6d5b72"
- },
- "attributes": {
- "type": "file",
- "name": "hello.txt",
- "trashed": false,
- "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": [],
- "size": 12,
- "executable": false,
- "class": "document",
- "mime": "text/plain"
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "data": {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "meta": {
+ "rev": "1-0e6d5b72"
+ },
+ "attributes": {
+ "type": "file",
+ "name": "hello.txt",
+ "trashed": false,
+ "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": [],
+ "size": 12,
+ "executable": false,
+ "class": "document",
+ "mime": "text/plain"
+ },
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ }
+ }
},
- "data": {
- "type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "links": {
+ "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
}
- }
- },
- "links": {
- "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
}
- }
}
```
@@ -547,9 +544,12 @@ rename/move it. The difference is the first one uses an id to identify the
file/directory to update, and the second one uses the path.
Some specific attributes of the patch can be used:
- - `dir_id` attribute can be updated to move a file or directory
- - `move_to_trash` boolean to specify that the file needs to be moved to the trash
- - `permanent_delete` boolean to specify that the files needs to be deleted (after being trashed)
+
+- `dir_id` attribute can be updated to move a file or directory
+- `move_to_trash` boolean to specify that the file needs to be moved to the
+ trash
+- `permanent_delete` boolean to specify that the files needs to be deleted
+ (after being trashed)
#### HTTP headers
@@ -566,29 +566,29 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "attributes": {
- "type": "file",
- "name": "hi.txt",
- "dir_id": "f2f36fec-8018-11e6-abd8-8b3814d9a465",
- "tags": ["poem"]
+ "data": {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "attributes": {
+ "type": "file",
+ "name": "hi.txt",
+ "dir_id": "f2f36fec-8018-11e6-abd8-8b3814d9a465",
+ "tags": ["poem"]
+ }
}
- }
}
```
#### Status codes
-* 200 OK, when the file or directory metadata has been successfully updated
-* 400 Bad Request, when a the directory is asked to move to one of its
- sub-directories
-* 404 Not Found, when the file/directory wasn't existing
-* 412 Precondition Failed, when the `If-Match` header is set and doesn't match
- the last revision of the file/directory
-* 422 Unprocessable Entity, when the sent data is invalid (for example, the
- parent doesn't exist)
+- 200 OK, when the file or directory metadata has been successfully updated
+- 400 Bad Request, when a the directory is asked to move to one of its
+ sub-directories
+- 404 Not Found, when the file/directory wasn't existing
+- 412 Precondition Failed, when the `If-Match` header is set and doesn't match
+ the last revision of the file/directory
+- 422 Unprocessable Entity, when the sent data is invalid (for example, the
+ parent doesn't exist)
#### Response
@@ -600,40 +600,40 @@ Location: http://cozy.example.com/files/9152d568-7e7c-11e6-a377-37cbfb190b4b
```json
{
- "data": {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "meta": {
- "rev": "1-0e6d5b72"
- },
- "attributes": {
- "type": "file",
- "name": "hi.txt",
- "trashed": false,
- "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": ["poem"],
- "size": 12,
- "executable": false,
- "class": "document",
- "mime": "text/plain"
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/f2f36fec-8018-11e6-abd8-8b3814d9a465"
+ "data": {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "meta": {
+ "rev": "1-0e6d5b72"
+ },
+ "attributes": {
+ "type": "file",
+ "name": "hi.txt",
+ "trashed": false,
+ "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": ["poem"],
+ "size": 12,
+ "executable": false,
+ "class": "document",
+ "mime": "text/plain"
},
- "data": {
- "type": "io.cozy.files",
- "id": "f2f36fec-8018-11e6-abd8-8b3814d9a465"
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/f2f36fec-8018-11e6-abd8-8b3814d9a465"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "f2f36fec-8018-11e6-abd8-8b3814d9a465"
+ }
+ }
+ },
+ "links": {
+ "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
}
- }
- },
- "links": {
- "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
}
- }
}
```
@@ -651,20 +651,20 @@ Content-Type: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "meta": { "rev": "1-0e6d5b72" },
- "attributes": { "dir_id": "f2f36fec-8018-11e6-abd8-8b3814d9a465" }
- },
- {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4c",
- "meta": { "rev": "2-123123" },
- "attributes": { "move_to_trash": true }
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "meta": { "rev": "1-0e6d5b72" },
+ "attributes": { "dir_id": "f2f36fec-8018-11e6-abd8-8b3814d9a465" }
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4c",
+ "meta": { "rev": "2-123123" },
+ "attributes": { "move_to_trash": true }
+ }
+ ]
}
```
@@ -691,18 +691,18 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.files.archives",
- "attributes": {
- "name": "project-X",
- "ids": ["a51aeeea-4f79-11e7-9dc4-83f67e9494ab"],
- "files": [
- "/Documents/bills",
- "/Documents/images/sunset.jpg",
- "/Documents/images/eiffel-tower.jpg"
- ]
+ "data": {
+ "type": "io.cozy.files.archives",
+ "attributes": {
+ "name": "project-X",
+ "ids": ["a51aeeea-4f79-11e7-9dc4-83f67e9494ab"],
+ "files": [
+ "/Documents/bills",
+ "/Documents/images/sunset.jpg",
+ "/Documents/images/eiffel-tower.jpg"
+ ]
+ }
}
- }
}
```
@@ -715,16 +715,16 @@ Content-Type: application/vnd.api+json
```json
{
- "links": {
- "related": "/files/archive/4521DC87/project-X.zip"
- },
- "data": {
- "type": "io.cozy.files.archives",
- "id": "4521DC87",
- "attributes": {
- "href": "/files/archive/4521DC87/project-X.zip"
+ "links": {
+ "related": "/files/archive/4521DC87/project-X.zip"
+ },
+ "data": {
+ "type": "io.cozy.files.archives",
+ "id": "4521DC87",
+ "attributes": {
+ "href": "/files/archive/4521DC87/project-X.zip"
+ }
}
- }
}
```
@@ -801,54 +801,54 @@ Content-Type: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.files",
- "id": "df24aac0-7f3d-11e6-81c0-d38812bfa0a8",
- "meta": {
- "rev": "1-3b75377c"
- },
- "attributes": {
- "type": "file",
- "name": "foo.txt",
- "trashed": true,
- "md5sum": "YjAxMzQxZTc4MDNjODAwYwo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": [],
- "size": 123,
- "executable": false,
- "class": "document",
- "mime": "text/plain"
- },
- "links": {
- "self": "/files/trash/df24aac0-7f3d-11e6-81c0-d38812bfa0a8"
- }
- },
- {
- "type": "io.cozy.files",
- "id": "4a4fc582-7f3e-11e6-b9ca-278406b6ddd4",
- "meta": {
- "rev": "1-4a09030e"
- },
- "attributes": {
- "type": "file",
- "name": "bar.txt",
- "trashed": true,
- "md5sum": "YWVhYjg3ZWI0OWQzZjRlMAo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": [],
- "size": 456,
- "executable": false,
- "class": "document",
- "mime": "text/plain"
- },
- "links": {
- "self": "/files/trash/4a4fc582-7f3e-11e6-b9ca-278406b6ddd4"
- }
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.files",
+ "id": "df24aac0-7f3d-11e6-81c0-d38812bfa0a8",
+ "meta": {
+ "rev": "1-3b75377c"
+ },
+ "attributes": {
+ "type": "file",
+ "name": "foo.txt",
+ "trashed": true,
+ "md5sum": "YjAxMzQxZTc4MDNjODAwYwo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": [],
+ "size": 123,
+ "executable": false,
+ "class": "document",
+ "mime": "text/plain"
+ },
+ "links": {
+ "self": "/files/trash/df24aac0-7f3d-11e6-81c0-d38812bfa0a8"
+ }
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "4a4fc582-7f3e-11e6-b9ca-278406b6ddd4",
+ "meta": {
+ "rev": "1-4a09030e"
+ },
+ "attributes": {
+ "type": "file",
+ "name": "bar.txt",
+ "trashed": true,
+ "md5sum": "YWVhYjg3ZWI0OWQzZjRlMAo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": [],
+ "size": 456,
+ "executable": false,
+ "class": "document",
+ "mime": "text/plain"
+ },
+ "links": {
+ "self": "/files/trash/4a4fc582-7f3e-11e6-b9ca-278406b6ddd4"
+ }
+ }
+ ]
}
```
diff --git a/docs/import_export_exploration.md b/docs/import_export_exploration.md
deleted file mode 100644
index c18e075e6b6..00000000000
--- a/docs/import_export_exploration.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Format de fichier
-
-Les applications cozy peuvent utiliser des fichiers pour stocker du contenu
-binaire, comme des photos ou des PDF. Les métadonnées sont conservées dans
-CouchDB, mais les binaires peuvent accéder au système de fichier ou à une
-instance Swift.
-
-## Les formats standards utilisés pour :
-
-### Les fichiers/dossiers
-
-* les attributs étendus permettent à l’utilisateur d’un systeme de fichier
- d’associer des métadonnées. `https://godoc.org/github.com/ivaxer/go-xattr`
- librairie go supportant les attributs étendus
-
-* Extensible Metadata Platform ou XMP est un format de métadonnées basé sur XML.
- XMP permet d'enregistrer sous forme d'un document XML des informations
- relatives à un fichier XMP définit différentes méthodes pour stocker ce
- document XML au sein même de fichiers JPEG, GIF, HTML….
-
-* stocker les fichiers json avec les métadonnées dans un autre répertoire et les
- fichiers binaires à part pour pouvoir récupérer tous les fichiers lors de
- l’export et remettre tout ca correctement lors de l’import avec les json.
-
-### Les albums (?)
-
-* répertoires avec le nom de l’album contenant les photos associées
-
-### Les contacts
-
-Plusieurs formats sont utilisés et ceci peut provoquer des incompatibilités
-entre differents clients. Google propose par exemple au client les deux types de
-formats (vcard et csv) (Il prend en charge l'importation de fichiers CSV Ã
-partir d'Outlook, d'Outlook Express, de Yahoo! Mail, de Hotmail, d'Eudora et de
-certaines autres applications. Il prend également en charge l'importation de
-fichiers vCard à partir d'applications telles que le Carnet d'adresses Apple.)
-Les contacts iCloud sont importés et exportés au format vCard
-
-* vcard est un format standard ouvert d'échange de données personnelles (fichier
- d’extension .vcf)
-
-Exemple
-
-```
-BEGIN:VCARD
-VERSION:2.1
-FN:Jean Dupont
-N:Dupont;Jean
-ADR;WORK;PREF;QUOTED-PRINTABLE:;Bruxelles 1200=Belgique;6A Rue Th. Decuyper
-LABEL;QUOTED-PRINTABLE;WORK;PREF:Rue Th. Decuyper 6A=Bruxelles 1200=Belgique
-TEL;CELL:+1234 56789
-EMAIL;INTERNET:jean.dupont@example.com
-UID:
-END:VCARD
-```
-
-* csv format utilisé pour les contacts également
-
-Exemple
-
-```
-"Prenom","Nom","Email","Age"
-"Jean", "Petit", "jean@monsite.fr", "34"
-"Anne", "Le Gall", "anne@exemple.net", "21"
-"Pierre", "Diawara", "pierre@sonsite.com", "44"
-```
-
-### Les calendriers
-
-* iCalendar est un format de données défini pour les échanges de données de
- calendrier (fichier d’extension .ical, ou .ics comme owncloud)
-
-Exemple
-
-```
-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//hacksw/handcal//NONSGML v1.0//EN
-BEGIN:VEVENT
-DTSTART:19970714T170000Z
-DTEND:19970715T035959Z
-SUMMARY:Fête à la Bastille
-END:VEVENT
-END:VCALENDAR
-```
-
-## Les formats utilisés dans Cozy pour :
-
-### Les fichiers/dossiers
-
-* Un fichier est un contenu binaire avec certaines métadonnées. Un fichier Json
- dans CouchDB contient un champ `id`, un champ `rev` et des `métadonnées`. Ce
- fichier est relié au fichier binaire qui se trouve dans le systeme de fichier.
- Un fichier a un champ parent et lorsqu'il est deplacé dans l'arboresence on ne
- modifie que le fichier Json sans toucher au contenu dans le systeme de
- fichier. Dans CouchDB, les fichers sont indexés et ont une structure
- arborescente.
-
-### Les albums
-
-* L'album est un document dans CouchDB qui va lister les photos qu'il contient.
diff --git a/docs/instance.md b/docs/instance.md
index 5e470d6fe31..1643c70c26d 100644
--- a/docs/instance.md
+++ b/docs/instance.md
@@ -14,11 +14,11 @@ will be blocked in production environment.
**Exemple:**
-* `curl -H "Host: bob.cozycloud.cc" localhost:8080` →
- `localhost:5984/bob-cozycloud.cc`
-* `curl -H "Host: alice.cozycloud.cc" localhost:8080` →
- `localhost:5984/alice-cozycloud.cc`
-* `curl localhost:8080` → `localhost:5984/dev` (in dev mode only)
+- `curl -H "Host: bob.cozycloud.cc" localhost:8080` →
+ `localhost:5984/bob-cozycloud.cc`
+- `curl -H "Host: alice.cozycloud.cc" localhost:8080` →
+ `localhost:5984/alice-cozycloud.cc`
+- `curl localhost:8080` → `localhost:5984/dev` (in dev mode only)
## Creation
@@ -30,41 +30,41 @@ $ cozy-stack instances add ]
With some possible additional options
-* `--locale `
-* `--tz `
-* `--email `
-* `--apps `
+- `--locale `
+- `--tz `
+- `--email `
+- `--apps `
It registers the instance in a global couchdb database `global/instances`
```json
{
- "hostname": "example.cozycloud.cc",
- "dbprefix": "example-clozycloud-cc/",
- "fsroot": "/var/lib/cozy/example.cozycloud.cc/fs/"
+ "hostname": "example.cozycloud.cc",
+ "dbprefix": "example-clozycloud-cc/",
+ "fsroot": "/var/lib/cozy/example.cozycloud.cc/fs/"
}
```
and creates the proper databases ($PREFIX/$DOCTYPE) for these doctypes:
-* `io.cozy.apps`
-* `io.cozy.files`
-* `io.cozy.notifications`
-* `io.cozy.settings`
+- `io.cozy.apps`
+- `io.cozy.files`
+- `io.cozy.notifications`
+- `io.cozy.settings`
Then, it creates the following indexes for these doctypes :
-* **TODO :** complete this list of indexes
+- **TODO :** complete this list of indexes
Then, it creates some directories:
-* `/`, with the id `io.cozy.files.root-dir`
-* `/Apps`, with the id `io.cozy.files.apps-dir`
-* `/Documents`, with the id `io.cozy.files.documents-dir`
-* `/Documents/Downloads`, with the id `io.cozy.files.downloads-dir`
-* `/Documents/Pictures`, with the id `io.cozy.files.pictures-dir`
-* `/Documents/Music`, with the id `io.cozy.files.music-dir`
-* `/Documents/Videos`, with the id `io.cozy.files.videos-dir`
+- `/`, with the id `io.cozy.files.root-dir`
+- `/Apps`, with the id `io.cozy.files.apps-dir`
+- `/Documents`, with the id `io.cozy.files.documents-dir`
+- `/Documents/Downloads`, with the id `io.cozy.files.downloads-dir`
+- `/Documents/Pictures`, with the id `io.cozy.files.pictures-dir`
+- `/Documents/Music`, with the id `io.cozy.files.music-dir`
+- `/Documents/Videos`, with the id `io.cozy.files.videos-dir`
**The ids are forced to known values:** even if these directories are moved or
renamed, they can still be found for the permissions.
@@ -76,9 +76,9 @@ time the locale is set (during onboarding).
Then it creates the basic settings
-* `email` if an email was provided through the CLI
-* `locale` if a locale was provided through the CLI
-* `tz` if a timezone was provided through the CLI
+- `email` if an email was provided through the CLI
+- `locale` if a locale was provided through the CLI
+- `tz` if a timezone was provided through the CLI
Settings are created as named id in the `$PREFIX/io.cozy.settings` database.
During onboarding, the fields will be prefilled with these value if they were
diff --git a/docs/intents.md b/docs/intents.md
index 54f456abadf..21f8262ebdc 100644
--- a/docs/intents.md
+++ b/docs/intents.md
@@ -2,19 +2,19 @@
# Intents
-* [Overview](#overview)
-* [Glossary](#glossary)
-* [Proposal](#proposal)
- * [1. Manifest](#1-manifest)
- * [2. Intent Start](##2-intent-start)
- * [3. Service Resolution](#3-service-resolution)
- * [4. Handshake](#4-handshake)
- * [5. Processing & Terminating](#5-processing--terminating)
-* [Routes](#routes)
-* [Annexes](#annexes)
- * [Use cases](#use-cases)
- * [Bibliography & Prior Art](#bibliography--prior-art)
- * [Discarded Ideas](#discarded-ideas)
+- [Overview](#overview)
+- [Glossary](#glossary)
+- [Proposal](#proposal)
+ - [1. Manifest](#1-manifest)
+ - [2. Intent Start](##2-intent-start)
+ - [3. Service Resolution](#3-service-resolution)
+ - [4. Handshake](#4-handshake)
+ - [5. Processing & Terminating](#5-processing--terminating)
+- [Routes](#routes)
+- [Annexes](#annexes)
+ - [Use cases](#use-cases)
+ - [Bibliography & Prior Art](#bibliography--prior-art)
+ - [Discarded Ideas](#discarded-ideas)
## Overview
@@ -31,15 +31,15 @@ neither painful for the users nor the developers.
## Glossary
-* **Intent**: Intents, sometimes also called Activities, is a pattern used in
- environments where multiple apps with different purposes coexist. The idea is
- that any app can express the need to do _something_ that it can't do itself,
- and an app that _can_ do it will take over from there.
-* **Stack**: refers to [cozy-stack](https://github.com/cozy/cozy-stack/), the
- server-side part of the Cozy infrastructure.
-* **Client**: the client is the application that _starts_ an intent.
-* **Service**: the service is the application that _handles_ an intent started
- by a client.
+- **Intent**: Intents, sometimes also called Activities, is a pattern used in
+ environments where multiple apps with different purposes coexist. The idea
+ is that any app can express the need to do _something_ that it can't do
+ itself, and an app that _can_ do it will take over from there.
+- **Stack**: refers to [cozy-stack](https://github.com/cozy/cozy-stack/), the
+ server-side part of the Cozy infrastructure.
+- **Client**: the client is the application that _starts_ an intent.
+- **Service**: the service is the application that _handles_ an intent started
+ by a client.
## Proposal
@@ -54,18 +54,18 @@ Every app can register itself as a potential handler for one or more intents. To
do so, it must provide the following information for each intent it wishes to
handle:
-* `action`: A verb that describes what the service should do. The most common
- actions are `CREATE`, `EDIT`, `OPEN`, `PICK`, and `SHARE`. While we recommend
- using one of these verbs, the list is not exhaustive and may be extended by
- any app.
-* `type`: One or more types of data on which the service knows how to operate
- the `action`. A `type` can be expressed as a
- [MIME type](https://en.wikipedia.org/wiki/Media_type) or a
- [Cozy Document Type](https://github.com/cozy/cozy-stack/blob/master/docs/data-system.md#typing).
- The application must have permissions for any Cozy Document Type listed here.
- You can also think of the `type` as the intent's subject.
-* `href`: the relative URL of the route designed to handle this intent. A
- query-string with the intent id will be added to this URL.
+- `action`: A verb that describes what the service should do. The most common
+ actions are `CREATE`, `EDIT`, `OPEN`, `PICK`, and `SHARE`. While we
+ recommend using one of these verbs, the list is not exhaustive and may be
+ extended by any app.
+- `type`: One or more types of data on which the service knows how to operate
+ the `action`. A `type` can be expressed as a
+ [MIME type](https://en.wikipedia.org/wiki/Media_type) or a
+ [Cozy Document Type](https://github.com/cozy/cozy-stack/blob/master/docs/data-system.md#typing).
+ The application must have permissions for any Cozy Document Type listed
+ here. You can also think of the `type` as the intent's subject.
+- `href`: the relative URL of the route designed to handle this intent. A
+ query-string with the intent id will be added to this URL.
These informations must be provided in the manifest of the application, inside
the `intents` key.
@@ -123,27 +123,27 @@ the _client_.
To start an intent, it must specify the following information:
-* `action` : an action verb, which will be matched against the actions declared
- in services manifest files.
-* `type` : a **single** data type, which will be matched against the types
- declared in services manifest files.
+- `action` : an action verb, which will be matched against the actions
+ declared in services manifest files.
+- `type` : a **single** data type, which will be matched against the types
+ declared in services manifest files.
There are also two optional fields that can be defined at the start of the
intent:
-* `data`: Any data that the client wants to make available to the service.
- `data` must be a JSON object but its structure is left to the discretion of
- the client. The only exception is when `type` is a MIME type and the client
- wishes to send a file to the service. In that case, the file should be
- represented as a base-64 encoded [Data URL](http://dataurl.net/#about) and
- must be named `content`. This convention is also recomended when dealing with
- other intent `type`s. See the examples below for an example of this.
-* `permissions` : When `type` is a Cozy Document Type and the client expects to
- receive one or more documents as part of the reply from the service, the
- `permissions` field allows the client to request permissions for these
- documents. `permissions` is a list of HTTP Verbs. Refer
- [to this section](https://github.com/cozy/cozy-stack/blob/master/docs/permissions.md#verbs)
- of the permission documentation for more information.
+- `data`: Any data that the client wants to make available to the service.
+ `data` must be a JSON object but its structure is left to the discretion of
+ the client. The only exception is when `type` is a MIME type and the client
+ wishes to send a file to the service. In that case, the file should be
+ represented as a base-64 encoded [Data URL](http://dataurl.net/#about) and
+ must be named `content`. This convention is also recomended when dealing
+ with other intent `type`s. See the examples below for an example of this.
+- `permissions` : When `type` is a Cozy Document Type and the client expects
+ to receive one or more documents as part of the reply from the service, the
+ `permissions` field allows the client to request permissions for these
+ documents. `permissions` is a list of HTTP Verbs. Refer
+ [to this section](https://github.com/cozy/cozy-stack/blob/master/docs/permissions.md#verbs)
+ of the permission documentation for more information.
**Note**: if the intent's subject is a Cozy Doctype that holds references to
other Cozy Documents (such as an album referencing photos or a playlist
@@ -217,12 +217,12 @@ the intent.
The stack then stores the information for that intent:
-* A unique id for that intent
-* Client URL
-* Service URL
-* `action`
-* `type`
-* `permissions`
+- A unique id for that intent
+- Client URL
+- Service URL
+- `action`
+- `type`
+- `permissions`
Finally, the service URL is suffixed with `?intent=` followed by the intent's
id, and then sent to the client.
@@ -336,14 +336,14 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.intents",
- "attributes": {
- "action": "PICK",
- "type": "io.cozy.files",
- "permissions": ["GET"]
+ "data": {
+ "type": "io.cozy.intents",
+ "attributes": {
+ "action": "PICK",
+ "type": "io.cozy.files",
+ "permissions": ["GET"]
+ }
}
- }
}
```
@@ -356,27 +356,26 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "id": "77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
- "type": "io.cozy.intents",
- "attributes": {
- "action": "PICK",
- "type": "io.cozy.files",
- "permissions": ["GET"],
- "client": "https://contacts.cozy.example.net",
- "services": [
- {
- "slug": "files",
- "href":
- "https://files.cozy.example.net/pick?intent=77bcc42c-0fd8-11e7-ac95-8f605f6e8338"
+ "data": {
+ "id": "77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
+ "type": "io.cozy.intents",
+ "attributes": {
+ "action": "PICK",
+ "type": "io.cozy.files",
+ "permissions": ["GET"],
+ "client": "https://contacts.cozy.example.net",
+ "services": [
+ {
+ "slug": "files",
+ "href": "https://files.cozy.example.net/pick?intent=77bcc42c-0fd8-11e7-ac95-8f605f6e8338"
+ }
+ ]
+ },
+ "links": {
+ "self": "/intents/77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
+ "permissions": "/permissions/a340d5e0-d647-11e6-b66c-5fc9ce1e17c6"
}
- ]
- },
- "links": {
- "self": "/intents/77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
- "permissions": "/permissions/a340d5e0-d647-11e6-b66c-5fc9ce1e17c6"
}
- }
}
```
@@ -405,27 +404,26 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "id": "77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
- "type": "io.cozy.intents",
- "attributes": {
- "action": "PICK",
- "type": "io.cozy.files",
- "permissions": ["GET"],
- "client": "https://contacts.cozy.example.net",
- "services": [
- {
- "slug": "files",
- "href":
- "https://files.cozy.example.net/pick?intent=77bcc42c-0fd8-11e7-ac95-8f605f6e8338"
+ "data": {
+ "id": "77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
+ "type": "io.cozy.intents",
+ "attributes": {
+ "action": "PICK",
+ "type": "io.cozy.files",
+ "permissions": ["GET"],
+ "client": "https://contacts.cozy.example.net",
+ "services": [
+ {
+ "slug": "files",
+ "href": "https://files.cozy.example.net/pick?intent=77bcc42c-0fd8-11e7-ac95-8f605f6e8338"
+ }
+ ]
+ },
+ "links": {
+ "self": "/intents/77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
+ "permissions": "/permissions/a340d5e0-d647-11e6-b66c-5fc9ce1e17c6"
}
- ]
- },
- "links": {
- "self": "/intents/77bcc42c-0fd8-11e7-ac95-8f605f6e8338",
- "permissions": "/permissions/a340d5e0-d647-11e6-b66c-5fc9ce1e17c6"
}
- }
}
```
@@ -435,33 +433,33 @@ Content-Type: application/vnd.api+json
Here is a non exhaustive list of situations that _may_ use intents:
-* Configure a new connector account
-* Share a photo album via email
-* Add an attachment to an email
-* Attach a note to a contact
-* Create a contact based on an email
-* Save an attachment received in an email
-* Create a birthday event in a calendar, based on a contact
-* Create an event based on an email's content
-* Create an event based on an ICS file
-* Chose an avatar for a contact
-* Open a file from the file browser (music, PDF, image, ...)
-* Attach a receipt to an expense
-* Provide a tip for another application
+- Configure a new connector account
+- Share a photo album via email
+- Add an attachment to an email
+- Attach a note to a contact
+- Create a contact based on an email
+- Save an attachment received in an email
+- Create a birthday event in a calendar, based on a contact
+- Create an event based on an email's content
+- Create an event based on an ICS file
+- Chose an avatar for a contact
+- Open a file from the file browser (music, PDF, image, ...)
+- Attach a receipt to an expense
+- Provide a tip for another application
### Bibliography & Prior Art
-* Prior art:
- https://forum.cozy.io/t/cozy-tech-topic-inter-app-communication-architecture/2287
-* Web intents: http://webintents.org/
-* WebActivities: https://wiki.mozilla.org/WebAPI/WebActivities and
- https://developer.mozilla.org/en-US/docs/Archive/Firefox_OS/API/Web_Activities
-* Siri Intents:
- https://developer.apple.com/library/content/documentation/Intents/Conceptual/SiriIntegrationGuide/ResolvingandHandlingIntents.html#//apple_ref/doc/uid/TP40016875-CH5-SW1
-* Android Intents:
- https://developer.android.com/reference/android/content/Intent.html
-* iOS extensions:
- https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/index.html
+- Prior art:
+ https://forum.cozy.io/t/cozy-tech-topic-inter-app-communication-architecture/2287
+- Web intents: http://webintents.org/
+- WebActivities: https://wiki.mozilla.org/WebAPI/WebActivities and
+ https://developer.mozilla.org/en-US/docs/Archive/Firefox_OS/API/Web_Activities
+- Siri Intents:
+ https://developer.apple.com/library/content/documentation/Intents/Conceptual/SiriIntegrationGuide/ResolvingandHandlingIntents.html#//apple_ref/doc/uid/TP40016875-CH5-SW1
+- Android Intents:
+ https://developer.android.com/reference/android/content/Intent.html
+- iOS extensions:
+ https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/index.html
### Discarded Ideas
diff --git a/docs/jobs.md b/docs/jobs.md
index 7d1953e49cb..fe4a6168c3a 100644
--- a/docs/jobs.md
+++ b/docs/jobs.md
@@ -15,19 +15,19 @@ distributed infrastructures.
This doc introduces two cozy types:
-* `io.cozy.jobs` for jobs
-* `io.cozy.triggers` for triggers
+- `io.cozy.jobs` for jobs
+- `io.cozy.triggers` for triggers
## Triggers
Jobs can be launched by five different types of triggers:
-* `@at` to schedule a one-time job executed after at a specific time in the
- future
-* `@in` to schedule a one-time job executed after a specific amount of time
-* `@every` to schedule periodic jobs executed at a given fix interval
-* `@cron` to schedule recurring jobs scheduled at specific times
-* `@event` to launch a job after a change in the cozy
+- `@at` to schedule a one-time job executed after at a specific time in the
+ future
+- `@in` to schedule a one-time job executed after a specific amount of time
+- `@every` to schedule periodic jobs executed at a given fix interval
+- `@cron` to schedule recurring jobs scheduled at specific times
+- `@event` to launch a job after a change in the cozy
These five triggers have specific syntaxes to describe when jobs should be
scheduled. See below for more informations.
@@ -230,26 +230,26 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.jobs",
- "id": "123123",
- "attributes": {
- "domain": "me.cozy.tools",
- "worker": "sendmail",
- "options": {
- "priority": 3,
- "timeout": 60,
- "max_exec_count": 3
- },
- "state": "running",
- "queued_at": "2016-09-19T12:35:08Z",
- "started_at": "2016-09-19T12:35:08Z",
- "error": ""
- },
- "links": {
- "self": "/jobs/123123"
+ "data": {
+ "type": "io.cozy.jobs",
+ "id": "123123",
+ "attributes": {
+ "domain": "me.cozy.tools",
+ "worker": "sendmail",
+ "options": {
+ "priority": 3,
+ "timeout": 60,
+ "max_exec_count": 3
+ },
+ "state": "running",
+ "queued_at": "2016-09-19T12:35:08Z",
+ "started_at": "2016-09-19T12:35:08Z",
+ "error": ""
+ },
+ "links": {
+ "self": "/jobs/123123"
+ }
}
- }
}
```
@@ -269,16 +269,16 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "attributes": {
- "options": {
- "priority": 3,
- "timeout": 60,
- "max_exec_count": 3
- },
- "arguments": {} // any json value used as arguments for the job
+ "data": {
+ "attributes": {
+ "options": {
+ "priority": 3,
+ "timeout": 60,
+ "max_exec_count": 3
+ },
+ "arguments": {} // any json value used as arguments for the job
+ }
}
- }
}
```
@@ -286,26 +286,26 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.jobs",
- "id": "123123",
- "attributes": {
- "domain": "me.cozy.tools",
- "worker": "sendmail",
- "options": {
- "priority": 3,
- "timeout": 60,
- "max_exec_count": 3
- },
- "state": "running",
- "queued_at": "2016-09-19T12:35:08Z",
- "started_at": "2016-09-19T12:35:08Z",
- "error": ""
- },
- "links": {
- "self": "/jobs/123123"
+ "data": {
+ "type": "io.cozy.jobs",
+ "id": "123123",
+ "attributes": {
+ "domain": "me.cozy.tools",
+ "worker": "sendmail",
+ "options": {
+ "priority": 3,
+ "timeout": 60,
+ "max_exec_count": 3
+ },
+ "state": "running",
+ "queued_at": "2016-09-19T12:35:08Z",
+ "started_at": "2016-09-19T12:35:08Z",
+ "error": ""
+ },
+ "links": {
+ "self": "/jobs/123123"
+ }
}
- }
}
```
@@ -318,15 +318,15 @@ allowed):
```json
{
- "permissions": {
- "mail-from-the-user": {
- "description": "Required to send mails from the user to his/her friends",
- "type": "io.cozy.jobs",
- "verbs": ["POST"],
- "selector": "worker",
- "values": ["sendmail"]
+ "permissions": {
+ "mail-from-the-user": {
+ "description": "Required to send mails from the user to his/her friends",
+ "type": "io.cozy.jobs",
+ "verbs": ["POST"],
+ "selector": "worker",
+ "values": ["sendmail"]
+ }
}
- }
}
```
@@ -345,29 +345,29 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- {
- "attributes": {
- "domain": "cozy.tools:8080",
- "options": null,
- "queued_at": "2017-09-29T15:32:31.953878568+02:00",
- "started_at": "0001-01-01T00:00:00Z",
- "state": "queued",
- "worker": "log"
- },
- "id": "77689bca9634b4fb08d6ca3d1643de5f",
- "links": {
- "self": "/jobs/log/77689bca9634b4fb08d6ca3d1643de5f"
- },
- "meta": {
- "rev": "1-f823bcd2759103a5ad1a98f4bf083b36"
- },
- "type": "io.cozy.jobs"
+ "data": [
+ {
+ "attributes": {
+ "domain": "cozy.tools:8080",
+ "options": null,
+ "queued_at": "2017-09-29T15:32:31.953878568+02:00",
+ "started_at": "0001-01-01T00:00:00Z",
+ "state": "queued",
+ "worker": "log"
+ },
+ "id": "77689bca9634b4fb08d6ca3d1643de5f",
+ "links": {
+ "self": "/jobs/log/77689bca9634b4fb08d6ca3d1643de5f"
+ },
+ "meta": {
+ "rev": "1-f823bcd2759103a5ad1a98f4bf083b36"
+ },
+ "type": "io.cozy.jobs"
+ }
+ ],
+ "meta": {
+ "count": 0
}
- ],
- "meta": {
- "count": 0
- }
}
```
@@ -379,16 +379,15 @@ its permission to only one worker, like this:
```json
{
- "permissions": {
- "mail-from-the-user": {
- "description":
- "Required to know the number of jobs in the sendmail queues",
- "type": "io.cozy.jobs",
- "verbs": ["GET"],
- "selector": "worker",
- "values": ["sendmail"]
+ "permissions": {
+ "mail-from-the-user": {
+ "description": "Required to know the number of jobs in the sendmail queues",
+ "type": "io.cozy.jobs",
+ "verbs": ["GET"],
+ "selector": "worker",
+ "values": ["sendmail"]
+ }
}
- }
}
```
@@ -416,20 +415,20 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "attributes": {
- "type": "@event",
- "arguments": "io.cozy.invitations",
- "debounce": "10m",
- "worker": "sendmail",
- "worker_arguments": {},
- "options": {
- "priority": 3,
- "timeout": 60,
- "max_exec_count": 3
- }
+ "data": {
+ "attributes": {
+ "type": "@event",
+ "arguments": "io.cozy.invitations",
+ "debounce": "10m",
+ "worker": "sendmail",
+ "worker_arguments": {},
+ "options": {
+ "priority": 3,
+ "timeout": 60,
+ "max_exec_count": 3
+ }
+ }
}
- }
}
```
@@ -437,24 +436,24 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.triggers",
- "id": "123123",
- "attributes": {
- "type": "@every",
- "arguments": "30m10s",
- "debounce": "10m",
- "worker": "sendmail",
- "options": {
- "priority": 3,
- "timeout": 60,
- "max_exec_count": 3
- }
- },
- "links": {
- "self": "/jobs/triggers/123123"
+ "data": {
+ "type": "io.cozy.triggers",
+ "id": "123123",
+ "attributes": {
+ "type": "@every",
+ "arguments": "30m10s",
+ "debounce": "10m",
+ "worker": "sendmail",
+ "options": {
+ "priority": 3,
+ "timeout": 60,
+ "max_exec_count": 3
+ }
+ },
+ "links": {
+ "self": "/jobs/triggers/123123"
+ }
}
- }
}
```
@@ -466,16 +465,15 @@ restrict its permission to only one worker, like this:
```json
{
- "permissions": {
- "mail-from-the-user": {
- "description":
- "Required to send regularly mails from the user to his/her friends",
- "type": "io.cozy.triggers",
- "verbs": ["POST"],
- "selector": "worker",
- "values": ["sendmail"]
+ "permissions": {
+ "mail-from-the-user": {
+ "description": "Required to send regularly mails from the user to his/her friends",
+ "type": "io.cozy.triggers",
+ "verbs": ["POST"],
+ "selector": "worker",
+ "values": ["sendmail"]
+ }
}
- }
}
```
@@ -494,35 +492,35 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.triggers",
- "id": "123123",
- "attributes": {
- "type": "@every",
- "arguments": "30m10s",
- "worker": "sendmail",
- "options": {
- "priority": 3,
- "timeout": 60,
- "max_exec_count": 3
- },
- "current_state": {
- "status": "done",
- "last_success": "2017-11-20T13:31:09.01641731",
- "last_successful_job_id": "abcde",
- "last_execution": "2017-11-20T13:31:09.01641731",
- "last_executed_job_id": "abcde",
- "last_failure": "2017-11-20T13:31:09.01641731",
- "last_failed_job_id": "abcde",
- "last_error": "error value",
- "last_manual_execution": "2017-11-20T13:31:09.01641731",
- "last_manual_job_id": "abcde"
- }
- },
- "links": {
- "self": "/jobs/triggers/123123"
+ "data": {
+ "type": "io.cozy.triggers",
+ "id": "123123",
+ "attributes": {
+ "type": "@every",
+ "arguments": "30m10s",
+ "worker": "sendmail",
+ "options": {
+ "priority": 3,
+ "timeout": 60,
+ "max_exec_count": 3
+ },
+ "current_state": {
+ "status": "done",
+ "last_success": "2017-11-20T13:31:09.01641731",
+ "last_successful_job_id": "abcde",
+ "last_execution": "2017-11-20T13:31:09.01641731",
+ "last_executed_job_id": "abcde",
+ "last_failure": "2017-11-20T13:31:09.01641731",
+ "last_failed_job_id": "abcde",
+ "last_error": "error value",
+ "last_manual_execution": "2017-11-20T13:31:09.01641731",
+ "last_manual_job_id": "abcde"
+ }
+ },
+ "links": {
+ "self": "/jobs/triggers/123123"
+ }
}
- }
}
```
@@ -536,11 +534,11 @@ To use this endpoint, an application needs a permission on the type
Get the trigger current state, to give a big picture of the health of the
trigger.
-* last executed job status (`done`, `errored`, `queued` or `running`)
-* last executed job that resulted in a successful executoin
-* last executed job that resulted in an error
-* last executed job from a manual execution (not executed by the trigger
- directly)
+- last executed job status (`done`, `errored`, `queued` or `running`)
+- last executed job that resulted in a successful executoin
+- last executed job that resulted in an error
+- last executed job from a manual execution (not executed by the trigger
+ directly)
#### Request
@@ -553,22 +551,22 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.jobs.state",
- "id": "123123",
- "attributes": {
- "status": "done",
- "last_success": "2017-11-20T13:31:09.01641731",
- "last_successful_job_id": "abcde",
- "last_execution": "2017-11-20T13:31:09.01641731",
- "last_executed_job_id": "abcde",
- "last_failure": "2017-11-20T13:31:09.01641731",
- "last_failed_job_id": "abcde",
- "last_error": "error value",
- "last_manual_execution": "2017-11-20T13:31:09.01641731",
- "last_manual_job_id": "abcde"
+ "data": {
+ "type": "io.cozy.jobs.state",
+ "id": "123123",
+ "attributes": {
+ "status": "done",
+ "last_success": "2017-11-20T13:31:09.01641731",
+ "last_successful_job_id": "abcde",
+ "last_execution": "2017-11-20T13:31:09.01641731",
+ "last_executed_job_id": "abcde",
+ "last_failure": "2017-11-20T13:31:09.01641731",
+ "last_failed_job_id": "abcde",
+ "last_error": "error value",
+ "last_manual_execution": "2017-11-20T13:31:09.01641731",
+ "last_manual_job_id": "abcde"
+ }
}
- }
}
```
@@ -588,7 +586,7 @@ Get the jobs launched by the trigger with the specified ID.
Query parameters:
-* `Limit`: to specify the number of jobs to get out
+- `Limit`: to specify the number of jobs to get out
#### Request
@@ -601,16 +599,16 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.jobs",
- "id": "123123",
- "attributes": {},
- "links": {
- "self": "/jobs/123123"
- }
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.jobs",
+ "id": "123123",
+ "attributes": {},
+ "links": {
+ "self": "/jobs/123123"
+ }
+ }
+ ]
}
```
@@ -629,22 +627,22 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.jobs",
- "id": "123123",
- "attributes": {
- "domain": "me.cozy.tools",
- "worker": "sendmail",
- "options": {},
- "state": "running",
- "queued_at": "2016-09-19T12:35:08Z",
- "started_at": "2016-09-19T12:35:08Z",
- "error": ""
- },
- "links": {
- "self": "/jobs/123123"
+ "data": {
+ "type": "io.cozy.jobs",
+ "id": "123123",
+ "attributes": {
+ "domain": "me.cozy.tools",
+ "worker": "sendmail",
+ "options": {},
+ "state": "running",
+ "queued_at": "2016-09-19T12:35:08Z",
+ "started_at": "2016-09-19T12:35:08Z",
+ "error": ""
+ },
+ "links": {
+ "self": "/jobs/123123"
+ }
}
- }
}
```
@@ -680,7 +678,7 @@ Get the list of triggers.
Query parameters:
-* `Worker`: to filter only triggers associated with a specific worker.
+- `Worker`: to filter only triggers associated with a specific worker.
#### Request
@@ -693,16 +691,16 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.triggers",
- "id": "123123",
- "attributes": {},
- "links": {
- "self": "/jobs/triggers/123123"
- }
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.triggers",
+ "id": "123123",
+ "attributes": {},
+ "links": {
+ "self": "/jobs/triggers/123123"
+ }
+ }
+ ]
}
```
diff --git a/docs/jsonapi.md b/docs/jsonapi.md
index c9800850e13..b2274b75ee3 100644
--- a/docs/jsonapi.md
+++ b/docs/jsonapi.md
@@ -38,11 +38,10 @@ GET /data/some-type/some-id/relationships/references HTTP/1.1
```json
{
- "data": ["... 100 docs ..."],
- "links": {
- "next":
- "/data/some-type/some-id/relationships/references?page[limit]=100&page[cursor]=7845122548848454212"
- }
+ "data": ["... 100 docs ..."],
+ "links": {
+ "next": "/data/some-type/some-id/relationships/references?page[limit]=100&page[cursor]=7845122548848454212"
+ }
}
```
@@ -52,11 +51,10 @@ GET /data/some-type/some-id/relationships/references?page[limit]=10 HTTP/1.1
```json
{
- "data": ["... 10 docs ..."],
- "links": {
- "next":
- "/data/some-type/some-id/relationships/references?page[limit]=10&page[cursor]=5487ba7596"
- }
+ "data": ["... 10 docs ..."],
+ "links": {
+ "next": "/data/some-type/some-id/relationships/references?page[limit]=10&page[cursor]=5487ba7596"
+ }
}
```
@@ -66,7 +64,7 @@ GET /data/some-type/some-id/relationships/references?page[limit]=100&page[cursor
```json
{
- "data": ["... 20 docs ..."]
+ "data": ["... 20 docs ..."]
}
```
@@ -76,10 +74,9 @@ GET /data/some-type/some-id/relationships/references?page[limit]=10&page[skip]=0
```json
{
- "data": ["... 10 docs ..."],
- "links": {
- "next":
- "/data/some-type/some-id/relationships/references?page[limit]=10&page[skip]=10"
- }
+ "data": ["... 10 docs ..."],
+ "links": {
+ "next": "/data/some-type/some-id/relationships/references?page[limit]=10&page[skip]=10"
+ }
}
```
diff --git a/docs/konnectors_design.md b/docs/konnectors-design.md
similarity index 69%
rename from docs/konnectors_design.md
rename to docs/konnectors-design.md
index aa40d6a879a..f1043c5939a 100644
--- a/docs/konnectors_design.md
+++ b/docs/konnectors-design.md
@@ -2,6 +2,10 @@
# Konnectors
+:warning: **Note:** this documentation is outdated. It is kept for historical
+reasons and shows the design and trade-offs we have made initially. But a lot
+of things have changed since, so don't expect the things to be still the same.
+
## What we want ?
[Konnectors](https://github.com/cozy-labs/konnectors) is an application for Cozy
@@ -9,11 +13,11 @@ v2 that fetch data from different web sites and services, and save them into a
Cozy. The 50+ connectors represent a lot of work from the community. So, we want
to port it to Cozy v3. There will be 2 parts:
-* My Accounts, a client-side app, that will offer the possibility for the user
- to configure her accounts, and choose when to start the import of data (see
- [the architecture doc](https://github.com/cozy-labs/konnectors/blob/development/docs/client-side-architecture.md)).
-* Konnectors, a worker for the [job service](jobs.md), with the code to import
- data from the web sites.
+- My Accounts, a client-side app, that will offer the possibility for the user
+ to configure her accounts, and choose when to start the import of data (see
+ [the architecture doc](https://github.com/cozy-labs/konnectors/blob/development/docs/client-side-architecture.md)).
+- Konnectors, a worker for the [job service](jobs.md), with the code to import
+ data from the web sites.
## Security
@@ -22,14 +26,14 @@ to port it to Cozy v3. There will be 2 parts:
Konnectors is not just a random application. It's a very good target for attacks
on Cozy because of these specificities:
-* It run on the server, where there is no Content Security Policy, or firewall
- to protect the stack.
-* It has access to Internet, by design.
-* It is written in nodejs, with a lot of dependencies where it is easy to hide
- malicious code.
-* It is a collection of connectors written by a lot of people. We welcome these
- contributions, but it also means that we take into account that we can't
- review in depth all the contributions.
+- It run on the server, where there is no Content Security Policy, or firewall
+ to protect the stack.
+- It has access to Internet, by design.
+- It is written in nodejs, with a lot of dependencies where it is easy to hide
+ malicious code.
+- It is a collection of connectors written by a lot of people. We welcome
+ these contributions, but it also means that we take into account that we
+ can't review in depth all the contributions.
#### Access to couchdb
@@ -142,13 +146,13 @@ for just one command (technically, for a new session, not the current one).
One feature Linux provides here is namespaces. There are a bunch of different
kinds:
-* in a pid namespace you become PID 1 and then your children are other
- processes. All the other programs are gone
-* in a networking namespace you can run programs on any port you want without it
- conflicting with what’s already running
-* in a mount namespace you can mount and unmount filesystems without it
- affecting the host filesystem. So you can have a totally different set of
- devices mounted (usually less).
+- in a pid namespace you become PID 1 and then your children are other
+ processes. All the other programs are gone
+- in a networking namespace you can run programs on any port you want without
+ it conflicting with what’s already running
+- in a mount namespace you can mount and unmount filesystems without it
+ affecting the host filesystem. So you can have a totally different set of
+ devices mounted (usually less).
It turns out that making namespaces is totally easy! You can just run a program
called [unshare](http://man7.org/linux/man-pages/man1/unshare.1.html).
@@ -221,15 +225,15 @@ tool.
NsJail is:
-* easy to install : just a make away with standard build tools
-* offers a full list or isolation tools
-* lightly documented the only documentation is nsjail -h (also available in the
- main github page) and it is quite cryptic for a non-sysadmin like me. I could
- not find any help in any search engine. Some examples are available to run a
- back in an isolated process and work but I could not run a full nodejs (only
- nodejs -v worked)
-* The konnectors will need a full nodejs installed on the host
-* Is still actively maintained
+- easy to install : just a make away with standard build tools
+- offers a full list or isolation tools
+- lightly documented the only documentation is nsjail -h (also available in
+ the main github page) and it is quite cryptic for a non-sysadmin like me. I
+ could not find any help in any search engine. Some examples are available to
+ run a back in an isolated process and work but I could not run a full nodejs
+ (only nodejs -v worked)
+- The konnectors will need a full nodejs installed on the host
+- Is still actively maintained
### Rkt
@@ -241,19 +245,19 @@ and without forcing self-hosted users to do complicated installation procedures.
Rkt is :
-* easy to install : debian, rpm package available, archlinux community package :
- https://github.com/coreos/rkt/releases
-* has network isolation like docker
-* offers CPU, memory limitation, seccomp isolation (but the set of rules to use
- is out of my understanding)
-* is well [documented](https://coreos.com/rkt/docs/latest/), complete man pages,
- but not as well known as docker, then there is not a lot of things to find
- outside the official documentation.
-* can use docker image directly or can convert them to one runnable aci file
- with one simple cli command (rkt export)
-* is in active developpement but relatively stable regarding core features.
-* container images can be easily signed and the signature is checked by default
- when running a container.
+- easy to install : debian, rpm package available, archlinux community package
+ : https://github.com/coreos/rkt/releases
+- has network isolation like docker
+- offers CPU, memory limitation, seccomp isolation (but the set of rules to
+ use is out of my understanding)
+- is well [documented](https://coreos.com/rkt/docs/latest/), complete man
+ pages, but not as well known as docker, then there is not a lot of things to
+ find outside the official documentation.
+- can use docker image directly or can convert them to one runnable aci file
+ with one simple cli command (rkt export)
+- is in active developpement but relatively stable regarding core features.
+- container images can be easily signed and the signature is checked by
+ default when running a container.
I managed to run a nodejs container with just the following commands :
@@ -380,12 +384,12 @@ inside this directory. The lib directory will be the content of the
The konnector will be run with the following environment variables :
-* `COZY_CREDENTIALS` : containing the response to Oauth request as json string
-* `COZY_URL` : to know what instance is running the konnector
-* `COZY_FIELDS` : as a json string with all the values from the account
- associated to the konnector.
-* `COZY_PARAMETERS` : optional json string associated with the application, used
- to parameterize a konnector based on a common set of code.
+- `COZY_CREDENTIALS` : containing the response to Oauth request as json string
+- `COZY_URL` : to know what instance is running the konnector
+- `COZY_FIELDS` : as a json string with all the values from the account
+ associated to the konnector.
+- `COZY_PARAMETERS` : optional json string associated with the application,
+ used to parameterize a konnector based on a common set of code.
In the end of the konnector execution (or timeout), the logs are read in the
log.txt file and added to the konnector own log file (in VFS) and the run
@@ -396,9 +400,9 @@ directory is then destroyed.
This section is devoted to allow the user to use one account for multiple
konnectors. It will follow the following constraints in mind:
-* The migration path must be as easy as possible
-* The developpement and maintainance of konnector must also be as easy as
- possible
+- The migration path must be as easy as possible
+- The developpement and maintainance of konnector must also be as easy as
+ possible
### New doctype : io.cozy.accounts
@@ -480,62 +484,59 @@ problem. We are trying to find solution to handle that.
We found 3 possible solutions :
-* Install the konnector on VFS as tar.gz files with all the dependencies
- included by the konnector developper
- * advantages : easy for the konnector developper, as performant as a cp, no
- nedd for a compiled version of the konnector source, no duplication of code
- in the repo
- * drawbacks : The source are not readable in files application then more
- complicated to study the konnector source, not really nice... , still could
- take a lot of space on VFS
-* Use webpack with `target: node` option to make a node bundle of the
- dependencies
- * advantages : the konnector itself stays in clear on the VFS
- * drawbacks : forces a compilation of the sources and then a sync between the
- source and bundle in the git repo by the konnector developper, forces
- konnector developpers to use webpack.
-* Install the npm dependencies with yarn in an immutable cache (--cache-folder
- option) in a directory like deps-${konnector-git-sha1} not in VFS.
- * advantages : easier for the konnector developper, no particular dependency
- handling, no mandatory compilation, just a package.json in the git
- repository, the cache can be shared by instances
- * drawbacks : node only solution, maybe more work on the cozy-stack side
+- Install the konnector on VFS as tar.gz files with all the dependencies
+ included by the konnector developper
+ - advantages : easy for the konnector developper, as performant as a cp,
+ no nedd for a compiled version of the konnector source, no duplication
+ of code in the repo
+ - drawbacks : The source are not readable in files application then more
+ complicated to study the konnector source, not really nice... , still
+ could take a lot of space on VFS
+- Use webpack with `target: node` option to make a node bundle of the
+ dependencies
+ - advantages : the konnector itself stays in clear on the VFS
+ - drawbacks : forces a compilation of the sources and then a sync between
+ the source and bundle in the git repo by the konnector developper,
+ forces konnector developpers to use webpack.
+- Install the npm dependencies with yarn in an immutable cache (--cache-folder
+ option) in a directory like deps-${konnector-git-sha1} not in VFS.
+ - advantages : easier for the konnector developper, no particular
+ dependency handling, no mandatory compilation, just a package.json in
+ the git repository, the cache can be shared by instances
+ - drawbacks : node only solution, maybe more work on the cozy-stack side
## TODO
-* [x] How to install and update the konnectors?
-* [x] Are the konnectors installed once per server or per instance (in the VFS
- like client-side apps)?
-* [x] One git repository with all the konnectors (like now), or one repos per
- konnector? Same question for package.json
-* [ ] What API to list the konnectors for My Accounts?
-* [ ] What workflow for developing a konnector?
-* [ ] How to test konnectors?
-* [x] How are managed the locales? : declared in manfiest.konnector
-* [x] Which version of nodejs? Last LTS version bundled in a rocket container
-* [ ] Do you keep coffeescript? Or move every konnector to ES2017?
- * 28 konnectors in coffee
- * 22 konnectors in JS
-* [ ] What about weboob?
-* [ ] What roadmap for transforming the konnectors-v2 in konnectors-v3?
-* [x] What format for the konnectors manifest?
-* [x] What permissions for a konnector?
-* [ ] For konnectors that import files, how can we let the user select a folder
- and have an associated permission for the konnector in this folder (and
- not anywhere else on the virtual file system)?
-* [ ] Can we associate the data retrieved by a konnector to a "profile"? The
- goal is to allow a client-side to have a permission on this profile and be
- able to read all the data fetched by a given konnector (or is tied to an
- account)?
-* [ ] How are logged the data exported/synchronized by a "push" konnector?
-* [x] Analyze the konnectors node_modules
- * no compiled modules currently
- * 28 dependencies that install 65 MB for 271 modules in production
- * 71 dependencies that install 611 MB for 858 modules with dev
- dependencies
-* [ ] How are persisted the accounts?
-* [x] How is executed a konnector? In particular, how the credentials are given
- to the konnector?
-* [ ] what should expose a konnector (data, functions, etc)?
- * https://github.com/cozy-labs/konnectors/issues/695
-* [ ] How can we support konnectors with OAuth?
+- [x] How to install and update the konnectors?
+- [x] Are the konnectors installed once per server or per instance (in the VFS
+ like client-side apps)?
+- [x] One git repository with all the konnectors (like now), or one repos per
+ konnector? Same question for package.json
+- [ ] What API to list the konnectors for My Accounts?
+- [ ] What workflow for developing a konnector?
+- [ ] How to test konnectors?
+- [x] How are managed the locales? : declared in manfiest.konnector
+- [x] Which version of nodejs? Last LTS version bundled in a rocket container
+- [ ] Do you keep coffeescript? Or move every konnector to ES2017? _ 28
+ konnectors in coffee _ 22 konnectors in JS
+- [ ] What about weboob?
+- [ ] What roadmap for transforming the konnectors-v2 in konnectors-v3?
+- [x] What format for the konnectors manifest?
+- [x] What permissions for a konnector?
+- [ ] For konnectors that import files, how can we let the user select a
+ folder and have an associated permission for the konnector in this
+ folder (and not anywhere else on the virtual file system)?
+- [ ] Can we associate the data retrieved by a konnector to a "profile"? The
+ goal is to allow a client-side to have a permission on this profile and
+ be able to read all the data fetched by a given konnector (or is tied to
+ an account)?
+- [ ] How are logged the data exported/synchronized by a "push" konnector?
+- [x] Analyze the konnectors node_modules _ no compiled modules currently _ 28
+ dependencies that install 65 MB for 271 modules in production \* 71
+ dependencies that install 611 MB for 858 modules with dev dependencies
+- [ ] How are persisted the accounts?
+- [x] How is executed a konnector? In particular, how the credentials are
+ given to the konnector?
+- [ ] what should expose a konnector (data, functions, etc)? \*
+ https://github.com/cozy-labs/konnectors/issues/695
+- [ ] How can we support konnectors with OAuth?
diff --git a/docs/konnectors-workflow.md b/docs/konnectors-workflow.md
new file mode 100644
index 00000000000..5367d6e4b28
--- /dev/null
+++ b/docs/konnectors-workflow.md
@@ -0,0 +1,559 @@
+# Konnectors workflow
+
+## TL;DR
+
+
+
+
+
+
+## Types
+
+### Accounts
+
+`io.cozy.accounts` contains information for an account, including those for
+authentication (technically, they are encrypted by cozy-stack before being
+saved in CouchDB, but we will show them as the konnectors will see them):
+
+```json
+{
+ "auth": {
+ "login": "000000000",
+ "password": "**********"
+ },
+ "folderPath": "/Administratif/Free Mobile",
+ "label": "freemobile",
+ "namePath": "Free Mobile"
+}
+```
+
+Accounts are manipulated through the `/data/` API.
+
+**Note:** you can read more about the [accounts doctype
+here](https://docs.cozy.io/en/cozy-doctypes/docs/io.cozy.accounts/).
+
+### Konnectors
+
+`io.cozy.konnectors` are installed similarly to `io.cozy.apps` (see
+[doc](./konnectors.md))
+
+### Permissions
+
+Like client-side applications, each konnector has an associated
+`io.cozy.permissions`. These permissions are those listed on the manifest of
+the konnectors, and the stack will add a permission for the files on the folder
+choosen by the user.
+
+### Triggers
+
+`io.cozy.triggers` are used to define when konnectors are launched. See
+https://docs.cozy.io/en/cozy-stack/jobs/#post-jobstriggers
+
+
+## Complete flow example
+
+As a user, from the expenses management app, I have a clean flow to configure a
+connector to retrieve my travel expenses
+
+1 - User is in **my-expenses** and clicks on \[configure travels\]
+
+2 - **my-expenses** triggers an intent
+
+```javascript
+cozy.intents.start("CREATE", "io.cozy.konnectors", {
+ category: "transport"
+});
+```
+
+3 - the Store app catch the intent, fetch all available konnectors and let the
+user choose
+
+```http
+GET /registry?... HTTP/1.1
+```
+
+4 - the user chooses the trainline konnector. Its manifest looks like this:
+
+```json
+{
+ "name": "Trainline",
+ "type": "konnector",
+ "slug": "konnector-trainline",
+ "description": "Konnector for trainline . com",
+ "source": "https://github.com/konnectors/trainlines.git@build",
+ "developer": {
+ "name": "XXX",
+ "url": "https://www.xxx.fr"
+ },
+ "version": "3.0.0",
+ "licence": "AGPL-3.0",
+ "fields": {
+ "login": {
+ "type": "text"
+ },
+ "password": {
+ "type": "password"
+ },
+ "advancedFields": {
+ "folderPath": {
+ "advanced": true,
+ "isRequired": false
+ }
+ }
+ },
+ "category": "transport",
+ "frequency": "weekly",
+ "permissions": {
+ "events": {
+ "description": "Connect train bill with event in your calendar",
+ "type": "io.cozy.events",
+ "verbs": ["PATCH"]
+ }
+ }
+}
+```
+
+5 - the user clicks on install, and the install starts:
+
+```http
+POST /konnectors/trainline HTTP/1.1
+```
+
+6 - the Store then uses an intent to know which app can configure this konnector:
+
+```javascript
+cozy.intents.start("REDIRECT", "io.cozy.accounts", {
+ slug: "trainline"
+});
+```
+
+7 - the Store redirects to the Home. The Home asks the user for account config
+and create a folder to save the PDFs.
+
+8 - the Home also add a Reference from the konnector to the folder to prevent
+any accidental folder deletion:
+
+```http
+POST /files/123-selected-folder-id-123/relationships/referenced_by
+```
+
+```json
+{
+ "data": [
+ {
+ "type": "io.cozy.konnectors",
+ "id": "io.cozy.konnectors/trainlines"
+ }
+ ]
+}
+```
+
+9 - then the Home can create the account:
+
+```http
+POST /data/io.cozy.accounts HTTP/1.1
+```
+
+```json
+{
+ "account_type": "trainline",
+ "auth": {
+ "login": "xxxx",
+ "password": "yyyyy"
+ },
+ "folderPath": "/Administrative/Trainline"
+}
+```
+
+```http
+HTTP/1.1 200 OK
+```
+
+```json
+{
+ "_id": "123-account-id-123",
+ "_rev": "1-asasasasa",
+ "account_type": "trainline",
+ "auth": {
+ "login": "xxxx",
+ },
+ "folderPath": "/Administrative/Trainline"
+}
+```
+
+10 - the Home create the trigger:
+
+```http
+POST /jobs/io.cozy.triggers
+```
+
+```json
+{
+ "data": {
+ "attributes": {
+ "type": "@cron",
+ "arguments": "0 0 0 0 1 1 ",
+ "worker": "konnector",
+ "worker_arguments": {
+ "konnector": "trainline",
+ "account": "5165621628784562148955",
+ "folder_to_save": "877854878455"
+ }
+ }
+ }
+}
+```
+
+11 - and, finally, the Home runs the konnector for the first time:
+
+```http
+POST /jobs/triggers/abc159753/launch HTTP/1.1
+```
+
+12 - the Home uses the [realtime](./realtime.md) to be informed if the
+konnector fails to login or succeeds to import the PDFs.
+
+If the user wants to use several account, the Home can setup several triggers
+for the same konnector & various accounts.
+
+
+## Konnector Worker specs
+
+### Prepare the execution
+
+The cozy-stack prepares the execution of the konnector by doing these steps:
+
+- it checks that the konnector is not in maintenance in the registry (execpt
+ for manual execution)
+- it ensures that the konnector has a folder where it can write its files,
+ and has the permission to write in this folder.
+
+### Execute the konnector
+
+Start the konnector through nsjail, passing as ENV variables :
+
+ - `COZY_URL`: the starting instance URL
+ - `COZY_CREDENTIALS`: security token to communicate with Cozy
+ - `COZY_FIELDS`: JSON-encoded worker_arguments
+ - `COZY_PARAMETERS`: JSON-encoded parameters associated with the konnector
+ - `COZY_LANGUAGE`: the language field of the konnector (eg. "node" etc.)
+ - `COZY_LOCALE`: the locale of the user (eg. "en" etc.)
+ - `COZY_TIME_LIMIT`: how much time the konnector can run before being killed
+ - `COZY_JOB_ID`: id of the job
+ - `COZY_JOB_MANUAL_EXECUTION`: whether the job was started manually (in Home) or automatically (via a cron trigger or event)
+
+The konnector process can send events trough its stdout (newline separated JSON
+object), the konnector worker pass these events to the realtime hub as
+`io.cozy.jobs.events`.
+
+- Only JSON formatted events are forwarded to the client-side throught
+ realtime
+- Otherwise formatted lines (such as node Error) will be kept in some system
+ logs.
+
+Konnectors should NOT log the received account login values in production.
+
+### Konnector error handling
+
+The konnector can output json formated messages as stated before (the events)
+and those events will be typed and formatted like this:
+
+```javascript
+{
+ type: "messagetype", // can be "debug", "info", "warning", "error", and "critical"
+ message: "message" // can be any string
+}
+```
+
+If there is an error or critical message, the execution will be seen as a
+failure by cozy-stack. It's also the case if the konnector reaches the timeout
+or returns with a non-zero status code.
+
+**Note:** debug and info level are not transmitted to syslog, except if the
+instance is in debug mode. It would be too verbose to do otherwise.
+
+
+## OAuth
+
+### Doctypes
+
+`io.cozy.konnectors` gives their desiderata for an account
+
+```json
+{
+ "fields": {
+ "account": {
+ "doctype": "io.cozy.accounts",
+ "account_type": "maif",
+ "scope": "openid profile offline_access"
+ }
+ }
+}
+```
+
+`io.cozy.accounts` contains authentication information for an account, as well
+as the associated scope
+
+```json
+{
+ "name": "Mon Compte Maif",
+ "account_type": "maif",
+ "status": "connected",
+ "oauth": {
+ "access_token": "akosaksoakso",
+ "refresh_token": "okoakozkaozk",
+ "scope": "openid profile offline_access"
+ }
+}
+```
+
+`io.cozy.account_types` contains the oauth configuration:
+
+```json
+{
+ "_id": "service.example",
+ "grant_mode": "authorization_code",
+ "client_id": "the registered client id",
+ "client_secret": "client_secret is necessary for server-flow",
+ "auth_endpoint": "https://service.example/auth",
+ "token_endpoint": "https://api.service.example/token"
+}
+```
+
+`io.cozy.account_types` are not accessible to the applications: they are
+injected directly in CouchDB in a global database
+`secrets/io-cozy-accounts_type`.
+
+### Reminder OAuth flow
+
+**Service** is the website from which konnector aims to retrieve informations.
+**Stack** is the cozy stack.
+
+OAuth is divided in 3 steps:
+
+- Client Registration: the client application (the Stack) needs to be
+ registered with the Service
+- Obtaining & Refreshing Authorization: all the steps from `client_id` to
+ `access_token`, the Stack will handle those
+- Using the `access_token`: ideally, the konnector should only concern itself
+ with this part; it receives an `access_token` and uses it.
+
+#### Client Registration
+
+Before beginning the Grant process, most Services require the application to be
+registered with a defined `redirect_uri`.
+
+There are a lot of options, which we will choose from when actually
+implementing konnectors using them.
+
+### Manually
+
+Most services requires a human developer to create the client manually and
+define its redirect_uri. However each instance has its own domain, so for these
+services, we will need to:
+
+**A. Register a "proxy" client**, which is a static page performing redirections
+as needed, as was done for Facebook events in v2 konnectors. We will register a
+well known cozy domain, like `oauth-proxy.cozy.io` and registers it with all
+providers. The use and risks associated with this domain should be made clear to
+the user.
+
+**B. Register each Stack** with a redirect_uri on the main stack domain, if we
+go this way, the register_uri below moves from
+`bob.cozy.rocks/accounts/redirect` to `oauthcallback.cozy.rocks/redirect` and the
+domain will be prepended to the state. This is feasible at cozy scale, but
+requires more knowledge and work for self-hosters.
+
+#### Example: Google
+
+For example, these are the steps for creating the google `account_type` for the
+stack at .mycozy.cloud:
+
+- Go to https://console.developers.google.com
+- Select or Create Project (up left near the logo)
+- Enable desired APIs (TBD with usages)
+- Click "Credentials"
+- Create credentials > Oauth Client ID > Web application
+- Set redirectURI to
+ https://oauthcallback.mycozy.cloud/accounts/google/redirect
+- Copy and paste provided Client ID and Client Secret.
+
+Then save the data in the console
+
+```
+http PUT localhost:5984/secrets%2Fio-cozy-accounts_types/google
+grant_mode=authorization_code
+redirect_uri="https://oauthcallback.mycozy.cloud/accounts/google/redirect"
+token_mode=basic
+token_endpoint="https://www.googleapis.com/oauth2/v4/token"
+auth_endpoint="https://accounts.google.com/o/oauth2/v2/auth"
+client_id=$CLIENT_ID
+client_secret=$CLIENT_SECRET
+```
+
+#### Dynamic Registration Protocol
+
+A few services allows client to register programaticaly through the Dynamic
+Client Registration Protocol [RFC7591](https://tools.ietf.org/html/rfc7591), we
+should allow the Stack to register using this protocol when we first need to
+implement a Konnector connecting to such a Service.
+
+#### No redirect_url enforcement
+
+A few services allows to specify arbitrary redirect_url without registering
+beforehand as a client.
+
+### Authorization Grant flows
+
+#### webserver flow (Authorization Code Grant)
+
+A. In the cozy app (Home) give a link
+
+```html
+
+```
+
+**NOTE** the scope may depends on other fields being configured (checkboxes),
+this will be described in json in the konnectors manifest. The format will be
+determined upon implementation.
+
+**NOTE** To limit bandwidth and risk of state corruption, the cozy app should
+save its state under a random key into localStorage, the key is then passed as
+the state in this query.
+
+B. Service lets the user login, allows or denies the scope, then redirects to
+
+```http
+https://oauthcallback.cozy.rocks/accounts/service-name/redirect?
+ code=AUTH_CODE_HERE&
+ state=1234zyx
+```
+
+C. The Stack does Server side this request:
+
+```http
+POST https://api.service.example/oauth/access_token HTTP/1.1
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=authorization_code&
+ code=AUTH_CODE_HERE&
+ redirect_uri=https://oauthcallback.cozy.rocks/accounts/service-name/redirect&
+ client_id=CLIENT_ID&
+ client_secret=CLIENT_SECRET
+```
+
+D. The Service responds (server side) with:
+
+```json
+{
+ "access_token": "ACCESS_TOKEN",
+ "token_type": "bearer",
+ "expires_in": 2592000,
+ "refresh_token": "REFRESH_TOKEN",
+ "scope": "read",
+ "uid": 100101,
+ "info": {
+ "name": "Claude Douillet",
+ "email": "claude.douillet@example.com"
+ }
+}
+```
+
+This whole object is saved as-is into a `io.cozy.accounts` 's `extras` field.
+
+The known fields `access_token`, `refresh_token` & `scope` will be **also**
+saved on the account's `oauth` itself
+
+E. The Stack redirect the user to the cozy app:
+
+```http
+HTTP/1.1 302 Found
+Location: https://bob-home.cozy.rocks/?state=1234zyx&account=accountID
+```
+
+The Cozy app checks that the state is expected, and restores its state to the
+form but whith account completed.
+
+#### SPA flow (Implicit grant)
+
+A. The cozy app gives a link:
+
+```html
+
+```
+
+See server-flow for state rules.
+
+B. Service lets the user login, allows or denies the scope, then redirects to
+
+```http
+https://bob-home.cozy.rocks/?
+access_token=ACCESS_TOKEN&
+state=1234zyx
+```
+
+C. The Cozy app adds the token to the `io.cozy.accounts` and save it before
+starting konnector.
+
+### Accessing data
+
+Once we have an account, the Cozy app starts the konnector with the proper
+account id. The konnector can then fetch the account and use its `access_token`
+to performs a request to fetch data:
+
+```http
+POST https://api.service.com/resource HTTP/1.1
+Authorization: Bearer ACCESS_TOKEN
+```
+
+### Refreshing token
+
+When using the server-flow, we also get a refresh_token. It is used to get a new
+access_token when it expires. However, if konnectors are responsible for
+refreshing token there is a race condition risk :
+
+```
+(konnector A) GET https://api.service.com/resource TOKEN1 -> expired
+(konnector B) GET https://api.service.com/resource TOKEN1 -> expired
+(konnector A) POST https://api.service.com/token REFRESH_TOKEN -> TOKEN2a
+(konnector B) POST https://api.service.com/token REFRESH_TOKEN -> TOKEN2b
+(konnector A) GET https://api.service.com/token TOKEN2a -> invalid
+```
+
+To avoid this, the stack will be responsible to perform token refresh. A
+konnector can requires the stack to refresh an account token with an HTTP
+request.
+
+```http
+POST https://bob.cozy.rocks/accounts/:accountID/refresh HTTP/1.1
+```
+
+### Konnectors Marketplace Requirements
+
+The following is a few points to be careful for in konnectors when we start
+allowing non-cozy developped OAuth konnectors.
+
+- With SPA flow, because of advanced security concerns (confused deputy
+ problem), cozy should validate the `access_token`. However, the way to do
+ that depends on the provider and cannot be described in json, it is
+ therefore the responsibility of the konnector itself.
+
+### Account types security rules
+
+- With server flow, an evil account type with proper `auth_endpoint` but bad
+ `token_endpoint` could retrieve a valid token as well as cozy client secret.
+ The reviewer of an `account_type` should make sure both these endpoints are
+ on domains belonging to the Service provider.
+
+### Notes for MesInfos experiment
+
+- MAIF konnector uses the webserver flow without redirect_uri validation
+- Orange konnector uses the client-side proxy but hosted on their own servers
+ (/!\ redirect_uri vs redirect_url)
diff --git a/docs/konnectors.md b/docs/konnectors.md
index 22c0662869e..c79c3f72c2b 100644
--- a/docs/konnectors.md
+++ b/docs/konnectors.md
@@ -22,7 +22,7 @@ _via_ our [job system](jobs.md) and the [konnector worker](workers.md).
| short_description | a short description of the application |
| long_description | a long description of the application |
| source | where the files of the app can be downloaded |
-| developer | `name` and `url` for the developer (`{"name": "Cozy", "url": "https://cozy.io"}`) |
+| developer | `name` and `url` for the developer (`{"name": "Cozy", "url": "https://cozy.io"}`) |
| default_locale | the locale used for the name and description fields |
| locales | translations of the name and description fields in other locales |
| langs | list of languages tags supported by the application |
@@ -47,13 +47,13 @@ konnector has been installed or failed.
#### Status codes
-* 202 Accepted, when the konnector installation has been accepted.
-* 400 Bad-Request, when the manifest of the konnector could not be processed
- (for instance, it is not valid JSON).
-* 404 Not Found, when the manifest or the source of the konnector is not
- reachable.
-* 422 Unprocessable Entity, when the sent data is invalid (for example, the slug
- is invalid or the Source parameter is not a proper or supported url)
+- 202 Accepted, when the konnector installation has been accepted.
+- 400 Bad-Request, when the manifest of the konnector could not be processed
+ (for instance, it is not valid JSON).
+- 404 Not Found, when the manifest or the source of the konnector is not
+ reachable.
+- 422 Unprocessable Entity, when the sent data is invalid (for example, the
+ slug is invalid or the Source parameter is not a proper or supported url)
#### Query-String
@@ -152,13 +152,13 @@ Content-Type: application/vnd.api+json
#### Status codes
-* 202 Accepted, when the konnector installation has been accepted.
-* 400 Bad-Request, when the manifest of the konnector could not be processed
- (for instance, it is not valid JSON).
-* 404 Not Found, when the konnector with the specified slug was not found or
- when the manifest or the source of the konnector is not reachable.
-* 422 Unprocessable Entity, when the sent data is invalid (for example, the slug
- is invalid or the Source parameter is not a proper or supported url)
+- 202 Accepted, when the konnector installation has been accepted.
+- 400 Bad-Request, when the manifest of the konnector could not be processed
+ (for instance, it is not valid JSON).
+- 404 Not Found, when the konnector with the specified slug was not found or
+ when the manifest or the source of the konnector is not reachable.
+- 422 Unprocessable Entity, when the sent data is invalid (for example, the
+ slug is invalid or the Source parameter is not a proper or supported url)
## List installed konnectors
diff --git a/docs/konnectors_oauth.md b/docs/konnectors_oauth.md
deleted file mode 100644
index 23505a59674..00000000000
--- a/docs/konnectors_oauth.md
+++ /dev/null
@@ -1,251 +0,0 @@
-# Doctypes
-
-`io.cozy.konnectors` gives their desiderata for an account
-
-```json
-{
- "fields": {
- "account": {
- "doctype": "io.cozy.accounts",
- "account_type": "maif",
- "scope": "openid profile offline_access"
- }
- }
-}
-```
-
-`io.cozy.accounts` contains authentication information for an account, as well
-as the associated scope
-
-```json
-{
- "name": "Mon Compte Maif",
- "account_type": "maif",
- "status": "connected",
- "oauth": {
- "access_token": "akosaksoakso",
- "refresh_token": "okoakozkaozk",
- "scope": "openid profile offline_access"
- }
-}
-```
-
-`io.cozy.account_types` contains the oauth configuration
-
-```json
-{
- "_id": "service.example",
- "grant_mode": "authorization_code",
- "client_id": "the registered client id",
- "client_secret": "client_secret is necessary for server-flow",
- "auth_endpoint": "https://service.example/auth",
- "token_endpoint": "https://api.service.example/token"
-}
-```
-
-io.cozy.account_types should not be accessible to the applications. They will be
-loaded into the stack by infra and will be configurable through config files for
-self-hosters.
-
-# Reminder OAuth flow
-
-**Service** is the website from which konnector aims to retrieve informations.
-**Stack** is the cozy stack
-
-Oauth is divided in 3 steps
-
-* Client Registration: the client application (the Stack) needs to be registered
- with the Service.
-* Obtaining & Refreshing Authorization: all the steps from client_id to
- access_token, the Stack will handle those
-* Using the access_token: Ideally, the konnector should only concern itself with
- this part; it receives an access_token and uses it.
-
-# Client Registration
-
-Before beginning the Grant process, most Services require the application to be
-registered with a defined redirect_uri.
-
-**TL:DR** Lot of options, which we will choose from when actually implementing
-konnectors using them.
-
-## Manually
-
-Most services requires a human developer to create the client manually and
-define its redirect_uri. However each instance has its own domain, so for these
-services, we will need to:
-
-**A. Register a "proxy" client**, which is a static page performing redirections
-as needed, as was done for Facebook events in v2 konnectors. We will register a
-well known cozy domain, like `oauth-proxy.cozy.io` and registers it with all
-providers. The use and risks associated with this domain should be made clear to
-the user.
-
-**B. Register each Stack** with a redirect_uri on the main stack domain, if we
-go this way, the register_uri below moves from
-`bob.cozy.rocks/accounts/redirect` to `_cozy_oauth.cozy.rocks/redirect` and the
-domain will be prepended to the state. This is feasible at cozy scale, but
-requires more knowledge and work for self-hosters.
-
-## Dynamic Registration Protocol
-
-A few services allows client to register programaticaly through the Dynamic
-Client Registration Protocol [RFC7591](https://tools.ietf.org/html/rfc7591), we
-should allow the Stack to register using this protocol when we first need to
-implement a Konnector connecting to such a Service.
-
-## No redirect_url enforcement
-
-A few services allows to specify arbitrary redirect_url without registering
-beforehand as a client.
-
-# Authorization Grant flows
-
-## webserver flow (Authorization Code Grant)
-
-A. In SettingsApp give a link
-
-```html
-
-```
-
-**NOTE** the scope may depends on other fields being configured (checkboxes),
-this will be described in json in the konnectors manifest. The format will be
-determined upon implementation.
-
-**NOTE** To limit bandwidth and risk of state corruption, SettingsApp should
-save its state under a random key into localStorage, the key is then passed as
-the state in this query.
-
-B. Service let the user login, allow or deny scope Then redirect to
-
-```http
-https://bob.cozy.rocks/accounts/service-name/redirect? (url)
- code=AUTH_CODE_HERE&
- state=1234zyx
-```
-
-C. The Stack does Server side
-
-```http
-POST https://api.service.example/token
-Content-Type:
- grant_type=authorization_code&
- code=AUTH_CODE_HERE&
- redirect_uri=https://bob.cozy.rocks/accounts/service-name/redirect&
- client_id=CLIENT_ID&
- client_secret=CLIENT_SECRET
-```
-
-D. The Service responds (server side) with (json)
-
-```json
-{
- "access_token": "ACCESS_TOKEN",
- "token_type": "bearer",
- "expires_in": 2592000,
- "refresh_token": "REFRESH_TOKEN",
- "scope": "read",
- "uid": 100101,
- "info": { "name": "Claude Douillet", "email": "claude.douillet@example.com" }
-}
-```
-
-This whole object is saved as-is into a `io.cozy.accounts` 's `extras` field.
-
-The known fields `access_token`, `refresh_token` & `scope` will be **also**
-saved on the account's `oauth` itself
-
-E. The Stack redirect the user to SettingsApp
-
-```http
-HTTP/1.1 302 Found
-Location: https://bob-settings.cozy.rocks/?state=1234zyx&account=accountID
-```
-
-SettingsApp check the state is expected and restore its state to the form but
-whith account completed.
-
-## SPA flow (Implicit grant)
-
-A. In SettingsApp give a link
-
-```html
-
-```
-
-See server-flow for state rules.
-
-B. Service let the user login, allow or deny scope Then redirects to
-
-```http
-https://bob-settings.cozy.rocks/?
-access_token=ACCESS_TOKEN&
-state=1234zyx
-```
-
-C. SettingsApp adds the token to the `io.cozy.accounts` and save it before
-starting konnector.
-
-# Accessing data
-
-Once we have an account, SettingsApp starts the konnector with the proper
-account id. The konnector can then fetch the account and use its access_token to
-performs a request to fetch data
-
-```http
-POST https://api.service.com/resource
- Authorization: Bearer ACCESS_TOKEN
-```
-
-# Refreshing token
-
-When using the server-flow, we also get a refresh_token. It is used to get a new
-access_token when it expires. However, if konnectors are responsible for
-refreshing token there is a race condition risk :
-
-```
-(konnector A) GET https://api.service.com/resource TOKEN1 -> expired
-(konnector B) GET https://api.service.com/resource TOKEN1 -> expired
-(konnector A) POST https://api.service.com/token REFRESH_TOKEN -> TOKEN2a
-(konnector B) POST https://api.service.com/token REFRESH_TOKEN -> TOKEN2b
-(konnector A) GET https://api.service.com/token TOKEN2a -> invalid
-```
-
-To avoid this, the stack will be responsible to perform token refresh. A
-konnector can requires the stack to refresh an account token with an HTTP
-request.
-
-```
-POST https://bob-settings.cozy.rocks/accounts/:accountID/refresh
-```
-
-# Konnectors Marketplace Requirements
-
-The following is a few points to be careful for in konnectors when we start
-allowing non-cozy developped OAuth konnectors.
-
-* With SPA flow, because of advanced security concerns (confused deputy
- problem), cozy should validate the `access_token`. However, the way to do that
- depends on the provider and cannot be described in json, it is therefore the
- responsibility of the konnector itself.
-
-# Account types security rules
-
-* With server flow, an evil account type with proper `auth_endpoint` but bad
- `token_endpoint` could retrieve a valid token as well as cozy client secret.
- The reviewer of an `account_type` should make sure both these endpoints are on
- domains belonging to the Service provider.
-
-# Notes for MesInfos experiment
-
-* MAIF konnector uses the webserver flow without redirect_uri validation
-* Orange konnector uses the client-side proxy but hosted on their own servers
- (/!\ redirect_uri vs redirect_url)
diff --git a/docs/konnectors_workflow_example.md b/docs/konnectors_workflow_example.md
deleted file mode 100644
index 8909541d465..00000000000
--- a/docs/konnectors_workflow_example.md
+++ /dev/null
@@ -1,423 +0,0 @@
-# Konnectors workflow
-
-## Types
-
-### Accounts
-
-`io.cozy.accounts` contains authentification information for an account
-
-```json
-{
- "name": "Gmail Perso",
- "account_type": "google",
- "status": "connected",
- "auth": {
- "user": "my-personal-account@gmail.com",
- "password": "my-secret"
- }
-}
-```
-
-accounts are manipulated through the `/data/` API.
-
-#### Accounts fields
-
-* **name** User defined name for the account ("Perso", "Pro")
-* **account_type** A type of account, like "google" or "trainlines", a list will
- be published by Cozy Cloud for current konnectors and most commons one. It's
- recommended to use the associated website domain otherwise.
-* **status** one of "NoAttempt" "Connected" or "Errored"
-* **error** the (optional) error for last connection to this account
-* **auth** An object defining auth method for this account. For now only {login,
- password} is supported.
-
-OAuth accounts will be explored later. The auth fields will be encrypted on
-disk.
-
-Account permissions should appear different in permission modal.
-
-### Konnectors
-
-`io.cozy.konnectors` are installed similarly to `io.cozy.apps` (see
-[doc](./konnectors.md))
-
-### Permissions
-
-Like client-side applications, each konnector has an associated
-`io.cozy.permissions` with `type=app` doc.
-
-### Triggers
-
-`io.cozy.triggers` are used to define when konnectors are launched See
-https://docs.cozy.io/en/cozy-stack/jobs/#post-jobstriggers
-
----
-
-## Routes
-
-**konnectors**
-
-* [ ] `GET /konnectors/marketplace` Lists available konnectors
-* [x] `POST /konnectors/:slug?Source=xxxx` Installs a konnector
-* [ ] `GET /konnectors` Lists installed konnectors
-
-**triggers**
-
-* [x] `GET /jobs/triggers?Worker=konnector` Lists konnectors with a configured
- recurrence.
-* [x] `POST /jobs/triggers` Enables a konnector recurrence.
-* [x] `DELETE /jobs/triggers/:triggerid` Disables a konnector recurrence
-
-**jobs**
-
-* [x] `POST /jobs/queue/konnector` Starts a konnector now
-* [x] `GET /jobs/queue/konnector` Lists pending konnectors
-
----
-
-## Complete flow example
-
-As a user, from the expenses management app, I have a clean flow to configure a
-connector to retrieve my travel expenses
-
-1 - User is in **my-expenses** and clicks on [configure travels]
-
-2 - **my-expenses** triggers an intent
-
-```javascript
-cozy.intents.start("CREATE", "io.cozy.konnectors", {
- category: "transport"
-});
-```
-
-3 - SettingsApp catch the intent, fetch all available konnectors and let the
-user choose
-
-```http
-GET /konnectors/marketplace
-```
-
-4 - SettingsApp fetch selected konnector (trainlines) manifest
-
-```http
-GET /konnectors/manifests?Source=git://github.com/konnectors/trainlines.git
-```
-
-```json
-{
- "name": "Trainline",
- "type": "konnector",
- "slug": "konnector-trainline",
- "description": "Konnector for trainline . com",
- "source": "https://github.com/konnectors/trainlines.git@build",
- "developer": {
- "name": "XXX",
- "url": "https://www.xxx.fr"
- },
- "version": "3.0.0",
- "licence": "AGPL-3.0",
- "fields": {
- "save_folder": {
- "doctype": "io.cozy.files",
- "type": "folder",
- "verbs": ["ALL"]
- },
- "account": {
- "doctype": "io.cozy.accounts",
- "account_type": "trainlines",
- "accountFormat": "login,password"
- }
- },
- "category": "transport",
- "frequency": "weekly",
- "permissions": {
- "events": {
- "description": "Connect train bill with event in your calendar",
- "type": "io.cozy.events",
- "verbs": ["PATCH"]
- }
- }
-}
-```
-
-5 - SettingsApp asks the user for account config and create the io.cozy.accounts
-
-```http
-POST /data/io.cozy.accounts
-```
-
-```json
-{
- "account_type": "google",
- "status": "PENDING",
- "auth": {
- "login": "xxxx",
- "password": "yyyyy"
- }
-}
-```
-
-```http
-HTTP/1.1 200 OK
-```
-
-```json
-{
- "_id": "123-account-id-123",
- "_rev": "1-asasasasa",
- "account_type": "google",
- "status": "PENDING",
- "auth": {
- "login": "xxxx",
- "password": "yyyyy"
- }
-}
-```
-
-6 - SettingsApp asks the user for the additional "save_folder" config fields. It
-could for example use a PICK intents for files.
-
-7 - SettingsApp does install the konnector
-
-```http
-POST /konnectors/konnector-trainlines?Source=git://github.com/konnectors/trainlines.git
-```
-
-```http
-HTTP/1.1 200 OK
-```
-
-```json
-{
- "data": {
- "id":"io.cozy.konnectors/trainlines",
- "type":"io.cozy.konnectors",
- "attributes": {
- "name": "trainline",
- "state": "installing",
- "slug": "trainline",
- ...
- },
- "links": {
- "self":"/konnectors/trainline",
- "permissions":"/permissions/456-permission-doc-id-456"
- }
- }
-}
-```
-
-8 - SettingsApp changes the konnector permissions doc to include save folder
-
-```http
-PATCH /permissions/456-permission-doc-id-456
-```
-
-```json
-{
- "data": {
- "id": "456-permission-doc-id-456",
- "type": "io.cozy.permissions",
- "attributes": {
- "type": "app",
- "source_id": "io.cozy.konnectors/trainlines",
- "permissions": {
- "save_folder": {
- "type": "io.cozy.files",
- "verbs": ["ALL"],
- "values": ["123-selected-folder-id-123"]
- }
- }
- }
- }
-}
-```
-
-```http
-HTTP/1.1 200 OK
-```
-
-```json
-{
- "data": {
- "id": "456-permission-doc-id-456",
- "type": "io.cozy.permissions",
- "attributes": {
- "type": "app",
- "source_id": "io.cozy.konnectors/trainlines",
- "permissions": {
- "events": {
- "description": "Connect train bill with event in your calendar",
- "type": "io.cozy.events",
- "verbs": ["PATCH"]
- },
- "save_folder": {
- "type": "io.cozy.files",
- "verbs": ["ALL"],
- "values": ["123-selected-folder-id-123"]
- }
- }
- }
- }
-}
-```
-
-9 - SettingsApp add a Reference from konnector to folder to prevent folder
-destruction
-
-```http
-POST /files/123-selected-folder-id-123/relationships/referenced_by
-```
-
-```json
-{
- "data": [
- {
- "type": "io.cozy.konnectors",
- "id": "io.cozy.konnectors/trainlines"
- }
- ]
-}
-```
-
-10 - SettingsApp runs the konnector the first time
-
-```http
-POST /jobs/queue/konnector
-```
-
-```json
-{
- "data": {
- "attributes": {
- "arguments": {
- "konnector": "trainline",
- "account": "123-account-id-123",
- "folder_to_save": "123-selected-folder-id-123"
- }
- }
- }
-}
-```
-
-```http
-HTTP/1.1 200 OK
-```
-
-```json
-{
- "data": {
- "id": "789-job-id-789",
- "type": "io.cozy.jobs",
- "attributes": {
- "worker": "konnector",
- "options": {
- "priority": 3,
- "timeout": 60,
- "max_exec_count": 3
- },
- "arguments": {
- "konnector": "trainline",
- "account": "123-account-id-123",
- "folder_to_save": "123-selected-folder-id-123"
- },
- "state": "running",
- "try_count": 1,
- "queued_at": "2016-09-19T12:35:08Z",
- "started_at": "2016-09-19T12:35:08Z",
- "errors": [],
- "output": {}
- }
- }
-}
-```
-
-11 - SettingsApp follow konnector status to check if all is properly configured.
-It uses the [realtime](./realtime.md) to subscribes to changes on
-`789-job-id-789` and is therefore informed of it's status / errors / ect ...
-
-**TODO** Look at current konnectors sources to defines a protocol between
-konnectors and SettingsApp to display the nice progress modal.
-
-* [ ] 250 events imported
-* [ ] 150 / 3500 contacts importing
-* [ ] ...
-
-**TODO** there should be some persistence for jobs error / status
-
-12 - SettingsApp creates a trigger to setup the konnector recurence
-
-```http
-POST /jobs/io.cozy.triggers
-```
-
-```json
-{
- "data": {
- "attributes": {
- "type": "@cron",
- "arguments": "0 0 0 0 1 1 ",
- "worker": "konnector",
- "worker_arguments": {
- "konnector": "trainline",
- "account": "5165621628784562148955",
- "folder_to_save": "877854878455"
- }
- }
- }
-}
-```
-
-If the user wants to use several account, Settings can setup several triggers
-for the same konnector & various accounts.
-
-### Relations and DELETE CASCADE
-
-* When a konnector is deleted, its triggers should be deleted
-* When an account is deleted, its triggers should be deleted
-
-**TODO** Should stack validate konnector value on trigger creation / to be
-extended to all workers pre-validating worker arguments ?
-
-## Konnector Worker specs
-
-Start the konnector through Rkt, passing as ENV variables :
-
- - `COZY_URL`: the starting instance URL
- - `COZY_CREDENTIALS`: security token to communicate with Cozy
- - `COZY_FIELDS`: JSON-encoded worker_arguments
- - `COZY_PARAMETERS`: JSON-encoded parameters associated with the konnector
- - `COZY_LANGUAGE`: the language field of the konnector (eg. "node" etc.)
- - `COZY_LOCALE`: the locale of the user (eg. "en" etc.)
- - `COZY_TIME_LIMIT`: how much time the konnector has to run
- - `COZY_JOB_ID`: id of the job
- - `COZY_JOB_MANUAL_EXECUTION`: whether the job was started manually (in Collect) or automatically (via a cron trigger or event)
-
-The konnector process can send events trough it's stdout (newline separated JSON
-object), the konnector worker pass these events to the realtime hub as
-`io.cozy.jobs.events`.
-
-* Only JSON formatted events are forwarded to the client-side throught realtime
-* Otherwise formatted lines (such as node Error) will be kept in some system
- logs.
-
-Konnectors should NOT log the received account login values in production.
-
-### Konnector error handling
-
-Rocket does not allow to pass error output from the app to it's own error
-output. We have to find another way to pass error messages. Here is a
-proposition :
-
-The konnector will output json formated messages as stated before (the events)
-and those events will be typed and formatted like this :
-
-```javascript
-{
- type: "messagetype", // can be "error", "debug", "warning", and maybe "progress"
- message: "message" // can be any string
-}
-```
-
-For the case of "error" type, the message will be a string coming from a npm
-package shared between the data-connect application and the connectors to allow
-the data-connect application to display localized error messages.
diff --git a/docs/mango.md b/docs/mango.md
index dea2bd84c6e..bf0aa527cd4 100644
--- a/docs/mango.md
+++ b/docs/mango.md
@@ -20,9 +20,9 @@ Content-Type: application/json
```json
{
- "index": {
- "fields": ["calendar", "date"]
- }
+ "index": {
+ "fields": ["calendar", "date"]
+ }
}
```
@@ -37,19 +37,19 @@ Content-Type: application/json
```json
{
- "result": "created",
- "id": "_design/a5f4711fc9448864a13c81dc71e660b524d7410c",
- "name": "a5f4711fc9448864a13c81dc71e660b524d7410c"
+ "result": "created",
+ "id": "_design/a5f4711fc9448864a13c81dc71e660b524d7410c",
+ "name": "a5f4711fc9448864a13c81dc71e660b524d7410c"
}
```
### Details
-* if the doctype does not exist, the database is created.
-* if the index already exists, a `{result: "exists"}` is returned, but the
- response code is still 200
-* design doc & name can be provided in request. **This is not recommended**, let
- couchdb handle naming and deduplication.
+- if the doctype does not exist, the database is created.
+- if the index already exists, a `{result: "exists"}` is returned, but the
+ response code is still 200
+- design doc & name can be provided in request. **This is not recommended**,
+ let couchdb handle naming and deduplication.
```json
{
@@ -61,10 +61,10 @@ Content-Type: application/json
### possible errors :
-* 401 unauthorized (no authentication has been provided)
-* 403 forbidden (the authentication does not provide permissions for this
- action)
-* 500 internal server error
+- 401 unauthorized (no authentication has been provided)
+- 403 forbidden (the authentication does not provide permissions for this
+ action)
+- 500 internal server error
## Find documents
@@ -85,15 +85,15 @@ Content-Type: application/json
```json
{
- "selector": {
- "calendar": "perso",
- "date": { "$gt": "20161001T00:00:00" }
- },
- "limit": 2,
- "skip": 3,
- "sort": ["calendar", "date"],
- "fields": ["_id", "_type", "_date"],
- "use_index": "_design/a5f4711fc9448864a13c81dc71e660b524d7410c"
+ "selector": {
+ "calendar": "perso",
+ "date": { "$gt": "20161001T00:00:00" }
+ },
+ "limit": 2,
+ "skip": 3,
+ "sort": ["calendar", "date"],
+ "fields": ["_id", "_type", "_date"],
+ "use_index": "_design/a5f4711fc9448864a13c81dc71e660b524d7410c"
}
```
@@ -108,28 +108,30 @@ Content-Type: application/json
```json
{
- "docs": [
- {
- "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
- "_type": "io.cozy.events",
- "date": "20161023T160000Z"
- },
- {
- "_id": "6494e0ac-dfcb-472e84a9cbee",
- "_type": "io.cozy.events",
- "date": "20161013T160000Z"
- }
- ]
+ "docs": [
+ {
+ "_id": "6494e0ac-dfcb-11e5-88c1-472e84a9cbee",
+ "_type": "io.cozy.events",
+ "date": "20161023T160000Z"
+ },
+ {
+ "_id": "6494e0ac-dfcb-472e84a9cbee",
+ "_type": "io.cozy.events",
+ "date": "20161013T160000Z"
+ }
+ ]
}
```
### Details
-* If an index does not exist for the selector, an error 400 is returned
-* The sort field must contains all fields used in selector
-* The sort field must match an existing index
-* It is possible to sort in reverse direction `sort:[{"calendar":"desc"}, {"date": "desc"}]` but **all fields** must be sorted in same direction.
-* `use_index` is optional but recommended.
+- If an index does not exist for the selector, an error 400 is returned
+- The sort field must contains all fields used in selector
+- The sort field must match an existing index
+- It is possible to sort in reverse direction
+ `sort:[{"calendar":"desc"}, {"date": "desc"}]` but **all fields** must be
+ sorted in same direction.
+- `use_index` is optional but recommended.
## Pagination cookbook
@@ -143,9 +145,9 @@ If the limit cause some docs to not be returned, the response will have a
```json
{
- "limit": 100,
- "next": true,
- "docs": ["... first hundred docs ..."]
+ "limit": 100,
+ "next": true,
+ "docs": ["... first hundred docs ..."]
}
```
@@ -153,9 +155,9 @@ If the number of docs is lower or equal to the limit, next will be false
```json
{
- "limit": 100,
- "next": false,
- "docs": ["... less than a hundred docs ..."]
+ "limit": 100,
+ "next": false,
+ "docs": ["... less than a hundred docs ..."]
}
```
diff --git a/docs/move.md b/docs/move.md
index 28f7d258b37..37ba7e22717 100644
--- a/docs/move.md
+++ b/docs/move.md
@@ -5,14 +5,12 @@
## Export
A Cozy's user can ask at any time to export a snapshot of all its data and
-metadata. This export takes place asynchronously and is separated in two
-parts:
- * a metadata tarball containing the in a JSON format all the doctypes
- * multi-part files tarballs containing the files (or a subpart of the
- files)
+metadata. This export takes place asynchronously and is separated in two parts:
+_ a metadata tarball containing the in a JSON format all the doctypes _
+multi-part files tarballs containing the files (or a subpart of the files)
-The export process is part of a worker described in the [workers
-section](./workers.md#export) of the documentation.
+The export process is part of a worker described in the
+[workers section](./workers.md#export) of the documentation.
Endpoints described in this documentation require a permission on the
`io.cozy.exports` doctype.
@@ -23,13 +21,13 @@ This endpoint can be used to create a new export job.
Exports options fields are:
-* `parts_size` (optional) (int): the size in bytes of a tarball files part.
-* `max_age` (optional) (duration / nanosecs): the maximum age of the export
- data.
-* `with_doctypes` (optional) (string array): the list of whitelisted exported
- doctypes
-* `without_files` (optional) (boolean): whether or not the export contains the
- files index (if false, it is not possible to generate files tarball).
+- `parts_size` (optional) (int): the size in bytes of a tarball files part.
+- `max_age` (optional) (duration / nanosecs): the maximum age of the export
+ data.
+- `with_doctypes` (optional) (string array): the list of whitelisted exported
+ doctypes
+- `without_files` (optional) (boolean): whether or not the export contains the
+ files index (if false, it is not possible to generate files tarball).
#### Request
@@ -46,7 +44,7 @@ Content-Type: application/vnd.api+json
"attributes": {
"parts_size": 10240,
"with_doctypes": [],
- "without_files": false,
+ "without_files": false
}
}
}
@@ -58,22 +56,22 @@ This endpoint can be used to fetch the metadata of an export.
Exports fields are:
-* `parts_size` (int): the size in bytes of a tarball files part.
-* `parts_cursors` (string array): the list of cursors to access to the
- different files parts.
-* `parts_length` (int): number of parts
-* `with_doctypes` (string array): the list of whitelisted exported doctypes
- (if empty of null, all doctypes are exported)
-* `without_files` (boolean): whether or not the export contains the files
- index (if false, it is not possible to generate files tarball).
-* `state` (string): the state of the export (`"exporting"` / `"done"` /
- `"error"`).
-* `created_at` (string / time): the date of creation of the export
-* `expires_at` (string / time): the date of expiration of the export
-* `total_size` (int): the total size of the export metadata
-* `creation_duration` (int): the amount of nanoseconds taken for the creation
- of the export
-* `error` (string): an error string if the export is in an `"error"` state
+- `parts_size` (int): the size in bytes of a tarball files part.
+- `parts_cursors` (string array): the list of cursors to access to the
+ different files parts.
+- `parts_length` (int): number of parts
+- `with_doctypes` (string array): the list of whitelisted exported doctypes
+ (if empty of null, all doctypes are exported)
+- `without_files` (boolean): whether or not the export contains the files
+ index (if false, it is not possible to generate files tarball).
+- `state` (string): the state of the export (`"exporting"` / `"done"` /
+ `"error"`).
+- `created_at` (string / time): the date of creation of the export
+- `expires_at` (string / time): the date of expiration of the export
+- `total_size` (int): the total size of the export metadata
+- `creation_duration` (int): the amount of nanoseconds taken for the creation
+ of the export
+- `error` (string): an error string if the export is in an `"error"` state
#### Request
@@ -90,7 +88,7 @@ Content-Type: application/vnd.api+json
"type": "io.cozy.exports",
"id": "86dbb546ca49f0ed1ce0a1ff0d1b15e3",
"meta": {
- "rev": "2-XXX",
+ "rev": "2-XXX"
},
"attributes": {
"parts_size": 10240,
@@ -110,8 +108,8 @@ Content-Type: application/vnd.api+json
### GET /move/exports/data/:opaque-identifier?cursor=XXX
-This endpoint will download an archive containing the metadata and files of
-the user, as part of a multi-part download. The cursor given should be one of
-the defined in the export document `parts_cursors`.
+This endpoint will download an archive containing the metadata and files of the
+user, as part of a multi-part download. The cursor given should be one of the
+defined in the export document `parts_cursors`.
Only the first part of part of the data contains the metadata.
diff --git a/docs/moving.md b/docs/moving.md
index 0ccaa3fbdbf..a2aeae82440 100644
--- a/docs/moving.md
+++ b/docs/moving.md
@@ -14,12 +14,12 @@ You also have DNS and TLS certificates to change
Once we start doing some intercozy communication, we might have issues with the
transition period.
-* I export my "bob.cozycloud.cc" from host1 as a tarball
-* My friend A's cozy send me an update notification the message gets to host1
-* I trigger DNS change
-* My friend B's cozy send me something, its DNS is not up-to-date, the message
- gets to host1
-* DNS change is complete, all further messages will reach host2
+- I export my "bob.cozycloud.cc" from host1 as a tarball
+- My friend A's cozy send me an update notification the message gets to host1
+- I trigger DNS change
+- My friend B's cozy send me something, its DNS is not up-to-date, the message
+ gets to host1
+- DNS change is complete, all further messages will reach host2
The sharing protocol have to take into account the fact that a cozy can have
accepted a message, but then forget about it (better, as it also covers the
diff --git a/docs/notifications.md b/docs/notifications.md
index d1d91ec61f2..3bc089aea5d 100644
--- a/docs/notifications.md
+++ b/docs/notifications.md
@@ -7,47 +7,49 @@ notify for services message or state change that could be of interest to the
user, in an asynchronous manner.
These notifications are part of a "Notification Center" where the user can
-configure the behavior of these notifications and the channel in which they
-are sent.
+configure the behavior of these notifications and the channel in which they are
+sent.
## Declare application's notifications
Each application have to declare in its manifest the notifications it needs to
-send. The `notifications` fields of the manifest can be used to define all
-these notifications, with the following properties:
-
-* `collapsible` (boolean): defines a notification category for which only
- the last value is of interest to the user. For instance, a account-balance
- quota for a user's bank account: such notification is only useful as its
- last value.
-* `stateful` (boolean): defines a notification storing a piece of state: for
- each new notification, the stack will check that the last sent
- notification has a different state.
-* `multiple` (boolean): specify the possibility for a notification to have
- different sub-categories, defined by a programmable/dynamic identifier.
- `collapsible` and `stateful` properties are inherited for each sub-
- categories.
-* `default_priority`: default priority to use, with values "high" or
- "normal". This is propagated to the underlying mobile notifications
- system.
-* `templates`: a link list to templates file contained in the application folder that can be used to write the content of the notification, depending on the communication channel.
-
-In this documentation, we take the example of an application with the following notification:
+send. The `notifications` fields of the manifest can be used to define all these
+notifications, with the following properties:
+
+- `collapsible` (boolean): defines a notification category for which only the
+ last value is of interest to the user. For instance, a account-balance quota
+ for a user's bank account: such notification is only useful as its last
+ value.
+- `stateful` (boolean): defines a notification storing a piece of state: for
+ each new notification, the stack will check that the last sent notification
+ has a different state.
+- `multiple` (boolean): specify the possibility for a notification to have
+ different sub-categories, defined by a programmable/dynamic identifier.
+ `collapsible` and `stateful` properties are inherited for each sub-
+ categories.
+- `default_priority`: default priority to use, with values "high" or "normal".
+ This is propagated to the underlying mobile notifications system.
+- `templates`: a link list to templates file contained in the application
+ folder that can be used to write the content of the notification, depending
+ on the communication channel.
+
+In this documentation, we take the example of an application with the following
+notification:
```json
{
- "notifications": {
- "account-balance": {
- "description": "Alert the user when its account balance is negative",
- "collapsible": true, // only interested in the last value of the notification
- "multiple": true, // require sub-categories for each account
- "stateful": true, // piece of state to distinguish notifications
- "default_priority": "high", // high priority for this notification
- "templates": {
- "mail": "file:./notifications/account-balance-mail.tpl"
- }
+ "notifications": {
+ "account-balance": {
+ "description": "Alert the user when its account balance is negative",
+ "collapsible": true, // only interested in the last value of the notification
+ "multiple": true, // require sub-categories for each account
+ "stateful": true, // piece of state to distinguish notifications
+ "default_priority": "high", // high priority for this notification
+ "templates": {
+ "mail": "file:./notifications/account-balance-mail.tpl"
+ }
+ }
}
- }
}
```
@@ -59,19 +61,19 @@ This endpoint can be used to push a new notification to the user.
Notifications fields are:
-* `category` (string): name of the notification category
-* `category_id` (string): category name if the category is multiple
-* `title` (string): title of the notification (optionnal)
-* `message` (string): message of of the notification (optionnal)
-* `priority` (string): priority of the notification (`high` or `normal`),
- sent to the underlying channel to prioritize the notification
-* `state` (string): state of the notification, used for `stateful`
- notification categories, to distinguish notifications
-* `preferred_channels` (array of string): to select a list of preferred
- channels for this notification: either `"mobile"` or `"mail"`. The stack
- may chose another channels.
-* `data` (map): key/value map used to create the notification from its
- template, or sent in the notification payload for mobiles
+- `category` (string): name of the notification category
+- `category_id` (string): category name if the category is multiple
+- `title` (string): title of the notification (optionnal)
+- `message` (string): message of of the notification (optionnal)
+- `priority` (string): priority of the notification (`high` or `normal`), sent
+ to the underlying channel to prioritize the notification
+- `state` (string): state of the notification, used for `stateful`
+ notification categories, to distinguish notifications
+- `preferred_channels` (array of string): to select a list of preferred
+ channels for this notification: either `"mobile"` or `"mail"`. The stack may
+ chose another channels.
+- `data` (map): key/value map used to create the notification from its
+ template, or sent in the notification payload for mobiles
#### Request
@@ -84,21 +86,21 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "attributes": {
- "category": "account-balance",
- "category_id": "my-bank",
- "title": "Your account balance is not OK",
- "message": "Warning: we have detected a negative balance in your my-bank",
- "priority": "high",
- "state": "-1",
- "preferred_channels": ["mobile"],
- "data": {
- "key1": "value1",
- "key2": "value2"
- }
+ "data": {
+ "attributes": {
+ "category": "account-balance",
+ "category_id": "my-bank",
+ "title": "Your account balance is not OK",
+ "message": "Warning: we have detected a negative balance in your my-bank",
+ "priority": "high",
+ "state": "-1",
+ "preferred_channels": ["mobile"],
+ "data": {
+ "key1": "value1",
+ "key2": "value2"
+ }
+ }
}
- }
}
```
@@ -111,27 +113,27 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.notifications",
- "id": "c57a548c-7602-11e7-933b-6f27603d27da",
- "meta": {
- "rev": "1-1f2903f9a867"
- },
- "attributes": {
- "source_id": "cozy/app/bank/account-balance/my-bank",
- "originator": "app",
- "slug": "bank",
- "category": "account-balance",
- "category_id": "my-bank",
- "title": "Your account balance is not OK",
- "message": "Warning: we have detected a negative balance in your my-bank",
- "priority": "high",
- "state": "-1",
- "data": {
- "key1": "value1",
- "key2": "value2"
- }
+ "data": {
+ "type": "io.cozy.notifications",
+ "id": "c57a548c-7602-11e7-933b-6f27603d27da",
+ "meta": {
+ "rev": "1-1f2903f9a867"
+ },
+ "attributes": {
+ "source_id": "cozy/app/bank/account-balance/my-bank",
+ "originator": "app",
+ "slug": "bank",
+ "category": "account-balance",
+ "category_id": "my-bank",
+ "title": "Your account balance is not OK",
+ "message": "Warning: we have detected a negative balance in your my-bank",
+ "priority": "high",
+ "state": "-1",
+ "data": {
+ "key1": "value1",
+ "key2": "value2"
+ }
+ }
}
- }
}
```
diff --git a/docs/onboarding.md b/docs/onboarding.md
index fa349d8a518..24e568d9b96 100644
--- a/docs/onboarding.md
+++ b/docs/onboarding.md
@@ -28,15 +28,15 @@ All other steps are handled by the `onboarding` application.
The `onboarding` application SHOULD therefore provide the following features
-* When started with a `registerToken`, allow the user to create a passphrase
-* When started with a `contextToken`
- ([see auth doc](auth.md#how-to-get-a-token)) use it to retrieve instance
- document.
- * If the instance document is complete **according to the `onboarding` app**,
- redirect to `home` application.
- * Otherwise, performs whatever steps it deems necessary to fill out the
- instance (ask for user email, help set up `myaccounts` accounts, say thank
- you...)
+- When started with a `registerToken`, allow the user to create a passphrase
+- When started with a `contextToken`
+ ([see auth doc](auth.md#how-to-get-a-token)) use it to retrieve instance
+ document.
+ - If the instance document is complete **according to the `onboarding`
+ app**, redirect to `home` application.
+ - Otherwise, performs whatever steps it deems necessary to fill out the
+ instance (ask for user email, help set up `myaccounts` accounts, say
+ thank you...)
This makes cozy-stack simple and safer while allowing behaviour modification for
several install types by picking the correct `onboarding` application / branch.
@@ -52,8 +52,8 @@ When an user attempts to access the root of its instance
(`https://contacts.example.cozycloud.cc`), and she is not logged-in, she is
redirected :
-* If the instance has a `passphrase` set, to the `/login` page
-* If the instance has a `registerToken` set, to the `onboarding` application.
+- If the instance has a `passphrase` set, to the `/login` page
+- If the instance has a `registerToken` set, to the `onboarding` application.
After login, the user is always redirected to the `onboarding` application. It
is the `onboarding` application responsibility to check if registering is
@@ -65,8 +65,8 @@ See [settings](settings.md).
## Flow Example
-* The server administrator Bob creates an instance through the CLI. He knows the
- instance should be in french for an user named `alice`.
+- The server administrator Bob creates an instance through the CLI. He knows
+ the instance should be in french for an user named `alice`.
```
cozy-stack instances add alice.example.com --locale fr
@@ -77,29 +77,29 @@ The instance is created
```json
{
- "domain": "alice.example.com",
- "locale": "fr"
+ "domain": "alice.example.com",
+ "locale": "fr"
}
```
-* Eve knows Alice just had an instance created, she goes to
- `https://alice.cozycloud.cc`. There is no `registerToken`, so she only see a
- message (in french) along the lines of "This is the cozy for Alice Martin,
- this register link is incorrect, if you are Alice Martin please ask your
- sysadmin for a new link".
-* Alice navigates to `https://alice.cozycloud.cc?registerToken=42...42`
-* She is redirected to the `onboarding` application
-* The `onboarding` application receive the registerToken. It is the default
- onboarding application and therefore display the cozy cloud agreement and then
- ask for a Password.
-* The `onboarding` application use its `registerToken` to register the
- passphrase. Registering the passphrase automatically log Alice in and redirect
- her back to the `onboarding` app.
-* Afterward, the `onboarding` app receive its token normally through the
- `data-cozy-token` body attribute, as described in
- [auth documentation](./auth.md). and can do whatever it needs to do :
- * read from the instance document to prefill/bypass form fields
- * add more informations to the instance document.
- * create `io.cozy.accounts` documents for external accounts.
-* When the onboarding application is satisfied, Alice is redirected to the
- `home` application
+- Eve knows Alice just had an instance created, she goes to
+ `https://alice.cozycloud.cc`. There is no `registerToken`, so she only see a
+ message (in french) along the lines of "This is the cozy for Alice Martin,
+ this register link is incorrect, if you are Alice Martin please ask your
+ sysadmin for a new link".
+- Alice navigates to `https://alice.cozycloud.cc?registerToken=42...42`
+- She is redirected to the `onboarding` application
+- The `onboarding` application receive the registerToken. It is the default
+ onboarding application and therefore display the cozy cloud agreement and
+ then ask for a Password.
+- The `onboarding` application use its `registerToken` to register the
+ passphrase. Registering the passphrase automatically log Alice in and
+ redirect her back to the `onboarding` app.
+- Afterward, the `onboarding` app receive its token normally through the
+ `data-cozy-token` body attribute, as described in
+ [auth documentation](./auth.md). and can do whatever it needs to do :
+ - read from the instance document to prefill/bypass form fields
+ - add more informations to the instance document.
+ - create `io.cozy.accounts` documents for external accounts.
+- When the onboarding application is satisfied, Alice is redirected to the
+ `home` application
diff --git a/docs/permissions.md b/docs/permissions.md
index 8118900132e..e36eab15307 100644
--- a/docs/permissions.md
+++ b/docs/permissions.md
@@ -31,8 +31,8 @@ them later with the access token. The permissions are in the `scope` parameter.
The owner of a cozy instance can share some documents and files with other
users. It can be done in two ways:
-* If the other user also has a cozy, it can be a cozy-to-cozy sharing.
-* Else, the owner can give to him a link with a code.
+- If the other user also has a cozy, it can be a cozy-to-cozy sharing.
+- Else, the owner can give to him a link with a code.
## What is a permission?
@@ -51,11 +51,11 @@ allow to access and modify any file or directory.
Some known types:
-* `io.cozy.files`, for files and folder in the [VFS](files.md)
-* `io.cozy.apps`, for [apps](apps.md)
-* `io.cozy.settings`, for the [settings](settings.md)
-* `io.cozy.jobs` and `io.cozy.triggers`, for [jobs](jobs.md)
-* `io.cozy.oauth.clients`, to list and revoke [OAuth 2 clients](auth.md)
+- `io.cozy.files`, for files and folder in the [VFS](files.md)
+- `io.cozy.apps`, for [apps](apps.md)
+- `io.cozy.settings`, for the [settings](settings.md)
+- `io.cozy.jobs` and `io.cozy.triggers`, for [jobs](jobs.md)
+- `io.cozy.oauth.clients`, to list and revoke [OAuth 2 clients](auth.md)
### Verbs
@@ -85,9 +85,9 @@ done with two permissions. The first one is for the calendar:
```json
{
- "type": "io.cozy.calendars",
- "verbs": ["GET"],
- "values": ["1355812c-d41e-11e6-8467-53be4648e3ad"]
+ "type": "io.cozy.calendars",
+ "verbs": ["GET"],
+ "values": ["1355812c-d41e-11e6-8467-53be4648e3ad"]
}
```
@@ -95,10 +95,10 @@ And the other is for the events inside the calendar:
```json
{
- "type": "io.cozy.events",
- "verbs": ["GET"],
- "selector": "calendar-id",
- "values": ["1355812c-d41e-11e6-8467-53be4648e3ad"]
+ "type": "io.cozy.events",
+ "verbs": ["GET"],
+ "selector": "calendar-id",
+ "values": ["1355812c-d41e-11e6-8467-53be4648e3ad"]
}
```
@@ -119,25 +119,25 @@ Example:
```json
{
- "permissions": {
- "contacts": {
- "description": "Required for autocompletion on @name",
- "type": "io.cozy.contacts",
- "verbs": ["GET"]
- },
- "images": {
- "description": "Required for the background",
- "type": "io.cozy.files",
- "verbs": ["GET", "POST"],
- "values": ["io.cozy.files.music-dir"]
- },
- "mail": {
- "description": "Required to send a congratulations email to your friends",
- "type": "io.cozy.jobs",
- "selector": "worker",
- "values": ["sendmail"]
+ "permissions": {
+ "contacts": {
+ "description": "Required for autocompletion on @name",
+ "type": "io.cozy.contacts",
+ "verbs": ["GET"]
+ },
+ "images": {
+ "description": "Required for the background",
+ "type": "io.cozy.files",
+ "verbs": ["GET", "POST"],
+ "values": ["io.cozy.files.music-dir"]
+ },
+ "mail": {
+ "description": "Required to send a congratulations email to your friends",
+ "type": "io.cozy.jobs",
+ "selector": "worker",
+ "values": ["sendmail"]
+ }
}
- }
}
```
@@ -159,7 +159,7 @@ io.cozy.contacts io.cozy.files:GET:io.cozy.files.music-dir io.cozy.jobs:POST:sen
### Inspiration
-* [Access control on other similar platforms](https://news.ycombinator.com/item?id=12784999)
+- [Access control on other similar platforms](https://news.ycombinator.com/item?id=12784999)
## Routes
@@ -185,34 +185,33 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.permissions",
- "id": "5a9c1844-d427-11e6-ab36-2b684d437b0d",
- "attributes": {
- "type": "app",
- "source_id": "io.cozy.apps/my-awesome-game",
- "permissions": {
- "contacts": {
- "description": "Required for autocompletion on @name",
- "type": "io.cozy.contacts",
- "verbs": ["GET"]
- },
- "images": {
- "description": "Required for the background",
- "type": "io.cozy.files",
- "verbs": ["GET"],
- "values": ["io.cozy.files.music-dir"]
- },
- "mail": {
- "description":
- "Required to send a congratulations email to your friends",
- "type": "io.cozy.jobs",
- "selector": "worker",
- "values": ["sendmail"]
+ "data": {
+ "type": "io.cozy.permissions",
+ "id": "5a9c1844-d427-11e6-ab36-2b684d437b0d",
+ "attributes": {
+ "type": "app",
+ "source_id": "io.cozy.apps/my-awesome-game",
+ "permissions": {
+ "contacts": {
+ "description": "Required for autocompletion on @name",
+ "type": "io.cozy.contacts",
+ "verbs": ["GET"]
+ },
+ "images": {
+ "description": "Required for the background",
+ "type": "io.cozy.files",
+ "verbs": ["GET"],
+ "values": ["io.cozy.files.music-dir"]
+ },
+ "mail": {
+ "description": "Required to send a congratulations email to your friends",
+ "type": "io.cozy.jobs",
+ "selector": "worker",
+ "values": ["sendmail"]
+ }
+ }
}
- }
}
- }
}
```
@@ -223,8 +222,8 @@ via the `codes` parameter in the query string. These codes can then be sent to
other people as a way to give these permissions (sharing by links). The
parameter is comma separed list of values. The role of these values is to
identify the codes if you want to revoke some of them later. A `ttl` parameter
-can also be given to make the codes expires after a delay ([bigduration
-format](https://github.com/justincampbell/bigduration/blob/master/README.md)).
+can also be given to make the codes expires after a delay
+([bigduration format](https://github.com/justincampbell/bigduration/blob/master/README.md)).
**Note**: it is only possible to create a strict subset of the permissions
associated to the sent token.
@@ -241,19 +240,19 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.permissions",
- "attributes": {
- "source_id": "io.cozy.apps/my-awesome-game",
- "permissions": {
- "images": {
- "type": "io.cozy.files",
- "verbs": ["GET"],
- "values": ["io.cozy.files.music-dir"]
+ "data": {
+ "type": "io.cozy.permissions",
+ "attributes": {
+ "source_id": "io.cozy.apps/my-awesome-game",
+ "permissions": {
+ "images": {
+ "type": "io.cozy.files",
+ "verbs": ["GET"],
+ "values": ["io.cozy.files.music-dir"]
+ }
+ }
}
- }
}
- }
}
```
@@ -266,26 +265,26 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
- "type": "io.cozy.permissions",
- "attributes": {
- "type": "share",
- "source_id": "io.cozy.apps/my-awesome-game",
- "codes": {
- "bob": "yuot7NaiaeGugh8T",
- "jane": "Yohyoo8BHahh1lie"
- },
- "expires_at": 1483951978,
- "permissions": {
- "images": {
- "type": "io.cozy.files",
- "verbs": ["GET"],
- "values": ["io.cozy.files.music-dir"]
+ "data": {
+ "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
+ "type": "io.cozy.permissions",
+ "attributes": {
+ "type": "share",
+ "source_id": "io.cozy.apps/my-awesome-game",
+ "codes": {
+ "bob": "yuot7NaiaeGugh8T",
+ "jane": "Yohyoo8BHahh1lie"
+ },
+ "expires_at": 1483951978,
+ "permissions": {
+ "images": {
+ "type": "io.cozy.files",
+ "verbs": ["GET"],
+ "values": ["io.cozy.files.music-dir"]
+ }
+ }
}
- }
}
- }
}
```
@@ -311,26 +310,26 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
- "type": "io.cozy.permissions",
- "attributes": {
- "type": "share",
- "source_id": "io.cozy.apps/my-awesome-game",
- "codes": {
- "bob": "yuot7NaiaeGugh8T",
- "jane": "Yohyoo8BHahh1lie"
- },
- "expires_at": 1483951978,
- "permissions": {
- "images": {
- "type": "io.cozy.files",
- "verbs": ["GET"],
- "values": ["io.cozy.files.music-dir"]
+ "data": {
+ "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
+ "type": "io.cozy.permissions",
+ "attributes": {
+ "type": "share",
+ "source_id": "io.cozy.apps/my-awesome-game",
+ "codes": {
+ "bob": "yuot7NaiaeGugh8T",
+ "jane": "Yohyoo8BHahh1lie"
+ },
+ "expires_at": 1483951978,
+ "permissions": {
+ "images": {
+ "type": "io.cozy.files",
+ "verbs": ["GET"],
+ "values": ["io.cozy.files.music-dir"]
+ }
+ }
}
- }
}
- }
}
```
@@ -356,15 +355,15 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
- "type": "io.cozy.permissions",
- "attributes": {
- "codes": {
- "jane": "Yohyoo8BHahh1lie"
- }
+ "data": {
+ "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
+ "type": "io.cozy.permissions",
+ "attributes": {
+ "codes": {
+ "jane": "Yohyoo8BHahh1lie"
+ }
+ }
}
- }
}
```
@@ -380,17 +379,17 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
- "type": "io.cozy.permissions",
- "permissions": {
- "add-this": {
- "type": "io.cozy.files",
- "verbs": ["GET"],
- "values": ["some-picture-id"]
- }
+ "data": {
+ "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
+ "type": "io.cozy.permissions",
+ "permissions": {
+ "add-this": {
+ "type": "io.cozy.files",
+ "verbs": ["GET"],
+ "values": ["some-picture-id"]
+ }
+ }
}
- }
}
```
@@ -406,13 +405,13 @@ Accept: application/vnd.api+json
```json
{
- "data": {
- "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
- "type": "io.cozy.permissions",
- "permissions": {
- "remove-this": {}
+ "data": {
+ "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
+ "type": "io.cozy.permissions",
+ "permissions": {
+ "remove-this": {}
+ }
}
- }
}
```
@@ -425,25 +424,25 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
- "type": "io.cozy.permissions",
- "attributes": {
- "type": "share",
- "source_id": "io.cozy.apps/my-awesome-game",
- "codes": {
- "bob": "yuot7NaiaeGugh8T"
- },
- "expires_at": 1483951978,
- "permissions": {
- "images": {
- "type": "io.cozy.files",
- "verbs": ["GET"],
- "values": ["io.cozy.files.music-dir"]
+ "data": {
+ "id": "a340d5e0-d647-11e6-b66c-5fc9ce1e17c6",
+ "type": "io.cozy.permissions",
+ "attributes": {
+ "type": "share",
+ "source_id": "io.cozy.apps/my-awesome-game",
+ "codes": {
+ "bob": "yuot7NaiaeGugh8T"
+ },
+ "expires_at": 1483951978,
+ "permissions": {
+ "images": {
+ "type": "io.cozy.files",
+ "verbs": ["GET"],
+ "values": ["io.cozy.files.music-dir"]
+ }
+ }
}
- }
}
- }
}
```
@@ -545,42 +544,42 @@ Content-Type: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.permissions",
- "id": "c47f82396d09bfcd270343c5855b30a0",
- "attributes": {
- "type": "share",
- "permissions": {
- "rule0": {
- "type": "io.cozy.events",
- "verbs": ["PATCH", "DELETE"],
- "values": ["c47f82396d09bfcd270343c5855b0eea"]
- }
- },
- "codes": { "bob": "secret" }
- },
- "meta": { "rev": "1-d46b6358683b80c8d59fc55d6de54127" },
- "links": { "self": "/permissions/c47f82396d09bfcd270343c5855b30a0" }
- },
- {
- "type": "io.cozy.permissions",
- "id": "c47f82396d09bfcd270343c5855b351a",
- "attributes": {
- "type": "share",
- "permissions": {
- "rule0": {
- "type": "io.cozy.events",
- "verbs": ["GET"],
- "values": ["c47f82396d09bfcd270343c5855b169b"]
- }
+ "data": [
+ {
+ "type": "io.cozy.permissions",
+ "id": "c47f82396d09bfcd270343c5855b30a0",
+ "attributes": {
+ "type": "share",
+ "permissions": {
+ "rule0": {
+ "type": "io.cozy.events",
+ "verbs": ["PATCH", "DELETE"],
+ "values": ["c47f82396d09bfcd270343c5855b0eea"]
+ }
+ },
+ "codes": { "bob": "secret" }
+ },
+ "meta": { "rev": "1-d46b6358683b80c8d59fc55d6de54127" },
+ "links": { "self": "/permissions/c47f82396d09bfcd270343c5855b30a0" }
},
- "codes": { "bob": "secret" }
- },
- "meta": { "rev": "1-920af658575a56e9e84685f1b09e5c23" },
- "links": { "self": "/permissions/c47f82396d09bfcd270343c5855b351a" }
- }
- ]
+ {
+ "type": "io.cozy.permissions",
+ "id": "c47f82396d09bfcd270343c5855b351a",
+ "attributes": {
+ "type": "share",
+ "permissions": {
+ "rule0": {
+ "type": "io.cozy.events",
+ "verbs": ["GET"],
+ "values": ["c47f82396d09bfcd270343c5855b169b"]
+ }
+ },
+ "codes": { "bob": "secret" }
+ },
+ "meta": { "rev": "1-920af658575a56e9e84685f1b09e5c23" },
+ "links": { "self": "/permissions/c47f82396d09bfcd270343c5855b351a" }
+ }
+ ]
}
```
diff --git a/docs/pouchdb-quirks.md b/docs/pouchdb-quirks.md
index 2b95ed50f13..bfed9d53378 100644
--- a/docs/pouchdb-quirks.md
+++ b/docs/pouchdb-quirks.md
@@ -1,31 +1,63 @@
# Pouchdb Mango Quirks
-The findings below were obtained while working on sorting performance in Cozy Drive. For reference, the final PR [can be seen here](https://github.com/cozy/cozy-drive/pull/1002/files).
+The findings below were obtained while working on sorting performance in Cozy
+Drive. For reference, the final PR
+[can be seen here](https://github.com/cozy/cozy-drive/pull/1002/files).
## Understanding what's going on
-Before diving into some of the quirks, it's important to understand some things when it comes to Pouchdb and especially Mango queries.
+Before diving into some of the quirks, it's important to understand some things
+when it comes to Pouchdb and especially Mango queries.
-First, you can add a plugin called `pouchdb-debug` and enable extra logs with `PouchDB.debug.enable( "pouchdb:find" );`. This will add explanation about the queries you run in the console and it's very helpful to understand what's going on under the hood.
+First, you can add a plugin called `pouchdb-debug` and enable extra logs with
+`PouchDB.debug.enable( "pouchdb:find" );`. This will add explanation about the
+queries you run in the console and it's very helpful to understand what's going
+on under the hood.
-You will realize that Pouchdb operates in 2 phases : one part of your query may be done using indexes, and the other may be done in memory. Long story short: anything done in memory has significant performance impacts, especially as the number of items gets larger. A more detailed guide can be found [here](https://www.bennadel.com/blog/3258-understanding-the-query-plan-explained-by-the-find-plugin-in-pouchdb-6-2-0.htm).
+You will realize that Pouchdb operates in 2 phases : one part of your query may
+be done using indexes, and the other may be done in memory. Long story short:
+anything done in memory has significant performance impacts, especially as the
+number of items gets larger. A more detailed guide can be found
+[here](https://www.bennadel.com/blog/3258-understanding-the-query-plan-explained-by-the-find-plugin-in-pouchdb-6-2-0.htm).
## About indexes
-Creating an index takes some time, but the first query will *also* take time — you are encouraged to warm up the indexes by firing a query that uses it before it is actually needed. An exemple implementation can be found [here](https://github.com/cozy/cozy-drive/blob/0326e3d253ca51e0fdb18a9e9b3b5c8ff0b87eba/src/drive/mobile/lib/replication.js#L15-L80).
+Creating an index takes some time, but the first query will _also_ take time —
+you are encouraged to warm up the indexes by firing a query that uses it before
+it is actually needed. An exemple implementation can be found
+[here](https://github.com/cozy/cozy-drive/blob/0326e3d253ca51e0fdb18a9e9b3b5c8ff0b87eba/src/drive/mobile/lib/replication.js#L15-L80).
-If there is a change in the underlying documents, the index will be partially recalculated on the next query. [The post-replication callback may be a good place to warm up the index again.](https://github.com/cozy/cozy-drive/blob/0326e3d253ca51e0fdb18a9e9b3b5c8ff0b87eba/src/drive/mobile/lib/replication.js#L86-L91)
+If there is a change in the underlying documents, the index will be partially
+recalculated on the next query.
+[The post-replication callback may be a good place to warm up the index again.](https://github.com/cozy/cozy-drive/blob/0326e3d253ca51e0fdb18a9e9b3b5c8ff0b87eba/src/drive/mobile/lib/replication.js#L86-L91)
-By default, Pouch will try to find the best index to use on your query. For more advanced queries, you generally want to force it with the `use_index` option. If the query and the index you force are not compatible, Pouch will emit an error and not run the query at all.
+By default, Pouch will try to find the best index to use on your query. For more
+advanced queries, you generally want to force it with the `use_index` option. If
+the query and the index you force are not compatible, Pouch will emit an error
+and not run the query at all.
## Indexing more than one field
-Creating an index on several fields is *not* the same as creating multiple indexes on one field each. The effects of a single index on multiple fields is illustrated in the [official docs](https://pouchdb.com/guides/mango-queries.html#more-than-one-field) and is important to understand.
+Creating an index on several fields is _not_ the same as creating multiple
+indexes on one field each. The effects of a single index on multiple fields is
+illustrated in the
+[official docs](https://pouchdb.com/guides/mango-queries.html#more-than-one-field)
+and is important to understand.
-Furthermore, the order in which fields are indexed on a multi-index is significant, most notably when it comes to sorting. If you declare an index on the fields `['name', 'age']`, you should also sort them by `['name', 'age']`. Sorting them in a different order or using other fields will likely be done in memory and kill your performance.
+Furthermore, the order in which fields are indexed on a multi-index is
+significant, most notably when it comes to sorting. If you declare an index on
+the fields `['name', 'age']`, you should also sort them by `['name', 'age']`.
+Sorting them in a different order or using other fields will likely be done in
+memory and kill your performance.
## Avoiding in memory selectors
-Filtering results with a selector on a field that has not been indexed is almost guaranteed to be done in memory and should be avoided. Since you can't have too many indexes, some filtering may have to be done in your own code — but if you can narrow down the results beforehand, that shouldn't be a problem.
+Filtering results with a selector on a field that has not been indexed is almost
+guaranteed to be done in memory and should be avoided. Since you can't have too
+many indexes, some filtering may have to be done in your own code — but if you
+can narrow down the results beforehand, that shouldn't be a problem.
-Even selectors on indexed field may end up being done in memory. Operators that don't rely on equality such as `$ne` should typically be avoided. Even equality operators run on secondary fields tend to be done in memory, and should therefor be used with care.
+Even selectors on indexed field may end up being done in memory. Operators that
+don't rely on equality such as `$ne` should typically be avoided. Even equality
+operators run on secondary fields tend to be done in memory, and should therefor
+be used with care.
diff --git a/docs/realtime.md b/docs/realtime.md
index 5b087d08e56..0a255bce9eb 100644
--- a/docs/realtime.md
+++ b/docs/realtime.md
@@ -4,24 +4,24 @@
### Definitions
-* **Event:** Something happening in the stack. Most of them will come from
- couchdb, some jobs and user actions might also trigger them.
-* **Events feed:** the feed of occurring events. There is two types of feeds:
- * **continuous** allows to follow events as they occurs
- * **interval** allow the see the history of the feed from any given time
-* **Realtime:** user experienced updates of the interface from change happening
- from another source. _Ie, I have a folder opened in cozy-files on the browser,
- I take some pictures from my smartphone, the pictures appears in the folder
- without me needing to refresh the browser tab._
+- **Event:** Something happening in the stack. Most of them will come from
+ couchdb, some jobs and user actions might also trigger them.
+- **Events feed:** the feed of occurring events. There is two types of feeds:
+ - **continuous** allows to follow events as they occurs
+ - **interval** allow the see the history of the feed from any given time
+- **Realtime:** user experienced updates of the interface from change
+ happening from another source. _Ie, I have a folder opened in cozy-files on
+ the browser, I take some pictures from my smartphone, the pictures appears
+ in the folder without me needing to refresh the browser tab._
### What couchdb offers
Couchdb supports with its `_changes` API both events feeds types:
-* using `since=now&continuous=true` we get all events **continuous**ly as they
- happen (SSE)
-* using `since=(last known seq_number)` we get all changes in the **interval**
- between last known `seq_number` and now.
+- using `since=now&continuous=true` we get all events **continuous**ly as they
+ happen (SSE)
+- using `since=(last known seq_number)` we get all changes in the **interval**
+ between last known `seq_number` and now.
Couchdb also offers a `_db_updates` route, which give us **continuous** changes
at the database level. This routes does not support a since parameter, as there
@@ -42,8 +42,8 @@ Couchdb replication algorithm can work in one-shot mode, where it replicates
changes since last sync up until now, or in continuous mode where it replicates
changes as they happens.
-* The stack will not allow continuous mode for replication.
-* This is already supported with the `_changes` route
+- The stack will not allow continuous mode for replication.
+- This is already supported with the `_changes` route
### Sharing
@@ -76,24 +76,24 @@ sharing from).
### Options
-* **Polling:** regularly ask the server what happened since last time.
-* **COMET:** Leaving a normal HTTP connection open sending data and heartbeets
- regularly to keep it open, reading xhr.responseText at intervals without
- waiting for readyState == 4. Restart the connection when it breaks.
-* **SSE:** Normalized & standardized version of COMET with
- [half-decent browser support (86% users)](http://caniuse.com/#feat=eventsource)
- but easily polyfillable (it's just COMET). It is simpler and easier to debug.
- It has some limitations (no HTTP headers in JS api, counts toward the maximum
- number of http connection per domain).
-* **Websocket:** keep a socket open, it allows 2 way data communication which we
- do not need, has
- [better server support (92% users)](http://caniuse.com/#feat=websockets) but
- is impossible to polyfill client side, more popular, there is a better
- [golang package](https://godoc.org/github.com/gorilla/websocket)
-* **SockJS & cie** they are **a lot** of packages which imitate Websocket API
- while using complicated client&server polyfill to allow support of older
- browser. [SockJS](https://github.com/sockjs/) is a drop-in websocket
- replacement with a go package and javascript client.
+- **Polling:** regularly ask the server what happened since last time.
+- **COMET:** Leaving a normal HTTP connection open sending data and heartbeets
+ regularly to keep it open, reading xhr.responseText at intervals without
+ waiting for readyState == 4. Restart the connection when it breaks.
+- **SSE:** Normalized & standardized version of COMET with
+ [half-decent browser support (86% users)](http://caniuse.com/#feat=eventsource)
+ but easily polyfillable (it's just COMET). It is simpler and easier to
+ debug. It has some limitations (no HTTP headers in JS api, counts toward the
+ maximum number of http connection per domain).
+- **Websocket:** keep a socket open, it allows 2 way data communication which
+ we do not need, has
+ [better server support (92% users)](http://caniuse.com/#feat=websockets) but
+ is impossible to polyfill client side, more popular, there is a better
+ [golang package](https://godoc.org/github.com/gorilla/websocket)
+- **SockJS & cie** they are **a lot** of packages which imitate Websocket API
+ while using complicated client&server polyfill to allow support of older
+ browser. [SockJS](https://github.com/sockjs/) is a drop-in websocket
+ replacement with a go package and javascript client.
### Choice = Websocket
@@ -103,21 +103,21 @@ older browser supports becomes necessary we can use SockJS.
### optimization paths (future)
-* **bandwidth** Limiting the number of events sent by allowing the client to
- specified it is only interested in events matching a selector _(files app only
- care about changes in the files of the current folder view)_
-* **number of connections** Instead of 1 socket / tab, we can probably make 1
- socket / browser using some hackish combination of SharedWorker /
- iframe.postMessage and a client-side demultiplexer.
-* **both** No need for realtime if the user is not using the tab (for most
- usecases), we could cut the realtime feed depending on
- [Page Visibility API](https://www.w3.org/TR/2011/WD-page-visibility-20110602/)
+- **bandwidth** Limiting the number of events sent by allowing the client to
+ specified it is only interested in events matching a selector _(files app
+ only care about changes in the files of the current folder view)_
+- **number of connections** Instead of 1 socket / tab, we can probably make 1
+ socket / browser using some hackish combination of SharedWorker /
+ iframe.postMessage and a client-side demultiplexer.
+- **both** No need for realtime if the user is not using the tab (for most
+ usecases), we could cut the realtime feed depending on
+ [Page Visibility API](https://www.w3.org/TR/2011/WD-page-visibility-20110602/)
## Go/Stack architecture
-* We assume all couchdb changes will originate from the stack
-* Events are generated at the stack level
-* We do **NOT** rely on couchdb `_changes?continuous` nor `_db_udpates`
+- We assume all couchdb changes will originate from the stack
+- Events are generated at the stack level
+- We do **NOT** rely on couchdb `_changes?continuous` nor `_db_udpates`
We create a realtime.Event interface, which we call in other packages. We accept
websocket connection and bind them to a realtime.Dispatcher object.
diff --git a/docs/references-docs-in-vfs.md b/docs/references-docs-in-vfs.md
index 5008529bd56..b656b430bad 100644
--- a/docs/references-docs-in-vfs.md
+++ b/docs/references-docs-in-vfs.md
@@ -32,51 +32,50 @@ The references of a file are listed in its JSON-API representation in the
```json
{
- "data": {
- "type": "io.cozy.files",
- "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
- "meta": {
- "rev": "1-0e6d5b72"
- },
- "attributes": {
- "type": "file",
- "name": "hello.txt",
- "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
- "created_at": "2016-09-19T12:38:04Z",
- "updated_at": "2016-09-19T12:38:04Z",
- "tags": [],
- "size": 12,
- "executable": false,
- "class": "document",
- "mime": "text/plain"
- },
- "relationships": {
- "parent": {
- "links": {
- "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ "data": {
+ "type": "io.cozy.files",
+ "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b",
+ "meta": {
+ "rev": "1-0e6d5b72"
},
- "data": {
- "type": "io.cozy.files",
- "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
- }
- },
- "referenced_by": {
- "links": {
- "self":
- "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81/relationships/references"
+ "attributes": {
+ "type": "file",
+ "name": "hello.txt",
+ "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=",
+ "created_at": "2016-09-19T12:38:04Z",
+ "updated_at": "2016-09-19T12:38:04Z",
+ "tags": [],
+ "size": 12,
+ "executable": false,
+ "class": "document",
+ "mime": "text/plain"
},
- "data": [
- {
- "type": "io.cozy.playlists",
- "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
- }
- ]
- }
- },
- "links": {
- "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
+ "relationships": {
+ "parent": {
+ "links": {
+ "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ },
+ "data": {
+ "type": "io.cozy.files",
+ "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81"
+ }
+ },
+ "referenced_by": {
+ "links": {
+ "self": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81/relationships/references"
+ },
+ "data": [
+ {
+ "type": "io.cozy.playlists",
+ "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
+ }
+ ]
+ }
+ },
+ "links": {
+ "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b"
+ }
}
- }
}
```
@@ -96,12 +95,12 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.playlists",
- "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.playlists",
+ "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
+ }
+ ]
}
```
@@ -126,12 +125,12 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.playlists",
- "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0"
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.playlists",
+ "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0"
+ }
+ ]
}
```
@@ -144,16 +143,16 @@ Content-Type: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.playlists",
- "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
- },
- {
- "type": "io.cozy.playlists",
- "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0"
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.playlists",
+ "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4"
+ },
+ {
+ "type": "io.cozy.playlists",
+ "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0"
+ }
+ ]
}
```
@@ -171,12 +170,12 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.playlists",
- "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0"
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.playlists",
+ "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0"
+ }
+ ]
}
```
@@ -214,12 +213,24 @@ Content-Type: application/vnd.api+json
```json
{
- "data": [
- { "type": "io.cozy.files", "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4" },
- { "type": "io.cozy.files", "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549" },
- { "type": "io.cozy.files", "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26" },
- { "type": "io.cozy.files", "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc" }
- ]
+ "data": [
+ {
+ "type": "io.cozy.files",
+ "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc"
+ }
+ ]
}
```
@@ -238,12 +249,24 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- { "type": "io.cozy.files", "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4" },
- { "type": "io.cozy.files", "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549" },
- { "type": "io.cozy.files", "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26" },
- { "type": "io.cozy.files", "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc" }
- ]
+ "data": [
+ {
+ "type": "io.cozy.files",
+ "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc"
+ }
+ ]
}
```
@@ -272,12 +295,24 @@ Accept: application/vnd.api+json
```json
{
- "data": [
- { "type": "io.cozy.files", "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4" },
- { "type": "io.cozy.files", "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549" },
- { "type": "io.cozy.files", "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26" },
- { "type": "io.cozy.files", "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc" }
- ]
+ "data": [
+ {
+ "type": "io.cozy.files",
+ "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26"
+ },
+ {
+ "type": "io.cozy.files",
+ "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc"
+ }
+ ]
}
```
@@ -295,10 +330,10 @@ Content-Type: application/vnd.api+json
Before an application updates a file, it can check if the file has some
references. If it is the case, it may offer to the user two choices:
-* update the file with the new version (the albums and playlists will use the
- new version)
-* save the new version as a new file and preserve the old file (the old file may
- be moved to a `originals` directory).
+- update the file with the new version (the albums and playlists will use the
+ new version)
+- save the new version as a new file and preserve the old file (the old file
+ may be moved to a `originals` directory).
### Moving a referenced file to the trash
@@ -315,7 +350,7 @@ Accept: application/vnd.api+json
```json
{
- "data": []
+ "data": []
}
```
@@ -334,11 +369,11 @@ references in a folder.
```js
map = function(doc) {
- if (doc.type === "folder") emit(doc.path);
+ if (doc.type === "folder") emit(doc.path);
};
query = {
- starkey: parent_folder_path + "/",
- endkey: parent_folder_path + "/\uFFFF"
+ starkey: parent_folder_path + "/",
+ endkey: parent_folder_path + "/\uFFFF"
};
```
diff --git a/docs/registry-publish.md b/docs/registry-publish.md
index a5b918f51dc..cd849c9cc13 100644
--- a/docs/registry-publish.md
+++ b/docs/registry-publish.md
@@ -7,10 +7,10 @@ on Travis to automatically publish new versions on the apps registry.
In this tutorial, we assume:
-* you have a token allowing you to publish applications for your `editor`:
- `AbCdEf`
-* you are working on a repository plugged on travis and named on github
- `cozy/cozy-example`
+- you have a token allowing you to publish applications for your `editor`:
+ `AbCdEf`
+- you are working on a repository plugged on travis and named on github
+ `cozy/cozy-example`
You first need to add the token to your travis configuration file `.travis.yml`.
To do so, you need the
@@ -34,12 +34,12 @@ script.
It contains environment variables that you can adapt as your need:
-* `COZY_APP_VERSION`: the version string of the deployed version
-* `COZY_APP_PARAMETERS`: an optional JSON object (string, object or array) that
- will parameterize the application on its execution.
-* `COZY_BUILD_URL`: the URL of the deployed tarball for your application
-* `COZY_BUILD_BRANCH`: the name of the build branch from which the script
- creates dev releases
+- `COZY_APP_VERSION`: the version string of the deployed version
+- `COZY_APP_PARAMETERS`: an optional JSON object (string, object or array)
+ that will parameterize the application on its execution.
+- `COZY_BUILD_URL`: the URL of the deployed tarball for your application
+- `COZY_BUILD_BRANCH`: the name of the build branch from which the script
+ creates dev releases
```bash
#!/bin/bash
diff --git a/docs/registry.md b/docs/registry.md
index 1e314d32ca8..207e48508b6 100644
--- a/docs/registry.md
+++ b/docs/registry.md
@@ -24,18 +24,19 @@ parameter you repository to automatically publish versions.
We differentiate three channels of release for each application:
-* stable: for stable releases
-* beta: for application that can be tested in advance
-* dev: for the latest releases directly from the trunk of the repository
+- stable: for stable releases
+- beta: for application that can be tested in advance
+- dev: for the latest releases directly from the trunk of the repository
For each of these channels, the version string has a different format which
differentiate the version channel:
-* stable: `X.Y.Z` where `X`, `Y` and `Z` are positive or null integers.
-* beta: `X.Y.Z-beta.M` where `X`, `Y`, `Z` and `M` are positive or null integers
-* dev: `X.Y.Z-dev.checksum` where `X`, `Y` and `Z` are positive or null integers
- and `checksum` is a unique identifier of the dev release (typically a shasum
- of the git commit)
+- stable: `X.Y.Z` where `X`, `Y` and `Z` are positive or null integers.
+- beta: `X.Y.Z-beta.M` where `X`, `Y`, `Z` and `M` are positive or null
+ integers
+- dev: `X.Y.Z-dev.checksum` where `X`, `Y` and `Z` are positive or null
+ integers and `checksum` is a unique identifier of the dev release (typically
+ a shasum of the git commit)
## Version order
@@ -63,45 +64,53 @@ An application object is **mutable**.
An application object contains the following fields:
-* `slug`: the application slug (unique)
-* `type`: the application type ("webapp" or "konnector")
-* `editor`: the application editor name
-* `versions`: an object containing all the channels versions
-* `latest_version`: the latest available version
-* `maintenance_activated`: boolean, true when the maintenance mode is activated on the application
-* `maintenance_options`: present only if `maintenance_activated` is true, object with the following fields:
- - `flag_infra_maintenance`: bool, true iff the maintenance is internal to the cozy infrastructure
- - `flag_short_maintenance`: bool, true iff the maintenance is a short maintenance, waiting for a correction on our side
- - `flag_disallow_manual_exec`: bool, true iff the maintenance will disallow the execution on the application, even when manually executed
- - `messages`: a list of localized messages containing a short and long information messages explaining the maintenance state
-* `label`: integer for a confidence grade from 0 to 5 (A to F), labelling the
- application from a user privacy standpoint. It is calculated from the
- `data_usage_commitment` and `data_usage_commitment_by` fields.
-* `data_usage_commitment`: specify a technical commitment from the
- application editor:
- - `user_ciphered`: technical commitment that the user's data is encrypted
- and can only be known by him.
- - `user_reserved`: commitment that the data is only used for the user, to
- directly offer its service.
- - `none`: no commitment
-* `data_usage_commitment_by`: specify what entity is taking the commitment:
- - `cozy`: the commitment is taken by cozy
- - `editor`: the commitment is taken by the application's editor
- - `none`: no commitment is taken
+- `slug`: the application slug (unique)
+- `type`: the application type ("webapp" or "konnector")
+- `editor`: the application editor name
+- `versions`: an object containing all the channels versions
+- `latest_version`: the latest available version
+- `maintenance_activated`: boolean, true when the maintenance mode is
+ activated on the application
+- `maintenance_options`: present only if `maintenance_activated` is true,
+ object with the following fields:
+ - `flag_infra_maintenance`: bool, true iff the maintenance is internal to
+ the cozy infrastructure
+ - `flag_short_maintenance`: bool, true iff the maintenance is a short
+ maintenance, waiting for a correction on our side
+ - `flag_disallow_manual_exec`: bool, true iff the maintenance will
+ disallow the execution on the application, even when manually executed
+ - `messages`: a list of localized messages containing a short and long
+ information messages explaining the maintenance state
+- `label`: integer for a confidence grade from 0 to 5 (A to F), labelling the
+ application from a user privacy standpoint. It is calculated from the
+ `data_usage_commitment` and `data_usage_commitment_by` fields.
+- `data_usage_commitment`: specify a technical commitment from the application
+ editor:
+ - `user_ciphered`: technical commitment that the user's data is encrypted
+ and can only be known by him.
+ - `user_reserved`: commitment that the data is only used for the user, to
+ directly offer its service.
+ - `none`: no commitment
+- `data_usage_commitment_by`: specify what entity is taking the commitment:
+ - `cozy`: the commitment is taken by cozy
+ - `editor`: the commitment is taken by the application's editor
+ - `none`: no commitment is taken
Example:
```json
{
- "slug": "drive",
- "type": "webapp",
- "editor": "cozy",
- "versions": {
- "stable": ["3.1.1"],
- "beta": ["3.1.1-beta.1"],
- "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"]
- },
- "latest_version": { /* */ }
+ "slug": "drive",
+ "type": "webapp",
+ "editor": "cozy",
+ "versions": {
+ "stable": ["3.1.1"],
+ "beta": ["3.1.1-beta.1"],
+ "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"]
+ },
+ "latest_version": {
+ /* */
+ }
}
```
@@ -113,16 +122,17 @@ A version object is **immutable**.
An application version object contains the following fields:
-* `slug`: the application slug
-* `type`: the application type (webapp, konnector, ...)
-* `manifest`: the [entire](./apps.md#the-manifest)
- [manifest](./konnectors.md#the-manifest) defined in the package
-* `created_at`: date of the release creation
-* `url`: URL of the tarball containing the application at specified version
-* `size`: the size of the application package (uncompressed) in bytes as string
-* `sha256`: the sha256 checksum of the application content
-* `tar_prefix`: optional tar prefix directory specified to properly extract the
- application content
+- `slug`: the application slug
+- `type`: the application type (webapp, konnector, ...)
+- `manifest`: the [entire](./apps.md#the-manifest)
+ [manifest](./konnectors.md#the-manifest) defined in the package
+- `created_at`: date of the release creation
+- `url`: URL of the tarball containing the application at specified version
+- `size`: the size of the application package (uncompressed) in bytes as
+ string
+- `sha256`: the sha256 checksum of the application content
+- `tar_prefix`: optional tar prefix directory specified to properly extract
+ the application content
The version string should follow the channels rule.
@@ -130,32 +140,32 @@ Example:
```json
{
- "slug": "drive",
- "type": "webapp",
- "version": "3.1.2",
- "created_at": "2017-07-05T07:54:40.982Z",
- "url": "http://.../3.1.2",
- "size": "1000",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "manifest": {
- /* ... */
- },
- "maintenance_activated": true,
- "maintenance_options": {
- "flag_infra_maintenance": true,
- "flag_short_maintenance": false,
- "flag_disallow_manual_exec": true,
- "messages": {
- "en": {
- "long_message": "The app is currently in maintenance because of ....",
- "short_message": "The app is currently in maintenance"
- },
- "fr": {
- "long_message": "L'application est en cours de maintenance à cause de ...",
- "short_message": "L'application est en cours de maintenance"
+ "slug": "drive",
+ "type": "webapp",
+ "version": "3.1.2",
+ "created_at": "2017-07-05T07:54:40.982Z",
+ "url": "http://.../3.1.2",
+ "size": "1000",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "manifest": {
+ /* ... */
+ },
+ "maintenance_activated": true,
+ "maintenance_options": {
+ "flag_infra_maintenance": true,
+ "flag_short_maintenance": false,
+ "flag_disallow_manual_exec": true,
+ "messages": {
+ "en": {
+ "long_message": "The app is currently in maintenance because of ....",
+ "short_message": "The app is currently in maintenance"
+ },
+ "fr": {
+ "long_message": "L'application est en cours de maintenance à cause de ...",
+ "short_message": "L'application est en cours de maintenance"
+ }
}
- }
- }
+ }
}
```
@@ -170,10 +180,10 @@ request should be a json object of an application.
#### Status codes
-* 201 Created, when the application has been successfully added
-* 409 Conflict, when an application with the same slug already exists
-* 400 Bad request, if the given application data is malformed (bad slug, missing
- editor, ...)
+- 201 Created, when the application has been successfully added
+- 409 Conflict, when an application with the same slug already exists
+- 400 Bad request, if the given application data is malformed (bad slug,
+ missing editor, ...)
#### Request
@@ -184,17 +194,17 @@ Authorization: Token AbCdE
```json
{
- "slug": "drive",
- "editor": "cozy",
- "name": {
- "en": "Drive",
- "fr": "Drive"
- },
- "description": {
- "en": "The drive application"
- },
- "repository": "https://github.com/cozy/cozy-drive",
- "tags": ["foo", "bar", "baz"]
+ "slug": "drive",
+ "editor": "cozy",
+ "name": {
+ "en": "Drive",
+ "fr": "Drive"
+ },
+ "description": {
+ "en": "The drive application"
+ },
+ "repository": "https://github.com/cozy/cozy-drive",
+ "tags": ["foo", "bar", "baz"]
}
```
@@ -207,30 +217,30 @@ The content of the manifest file extracted from the application data is used to
fill the fields of the version. Before adding the application version to the
registry, the registry should check the following:
-* the `manifest` file contained in the tarball should be checked and have its
- fields checked against the application properties
-* the application content should check the sha256 checksum
+- the `manifest` file contained in the tarball should be checked and have its
+ fields checked against the application properties
+- the application content should check the sha256 checksum
Fields of the object sent to this request:
-* **`url`**: the url where the application tarball is stored
-* **`sha256`**: the sha256 checksum of the tarball
-* **`version`**: the version value (should match the one in the manifest)
-* `parameters?`: an optional json value (any) that will override the
- `parameters` field of the manifest
-* `icon?`: an optional path to override the `icon` field of the manifest
-* `screenshots?`: and optional array of path to override the `screenshots` field
- of the manifest
+- **`url`**: the url where the application tarball is stored
+- **`sha256`**: the sha256 checksum of the tarball
+- **`version`**: the version value (should match the one in the manifest)
+- `parameters?`: an optional json value (any) that will override the
+ `parameters` field of the manifest
+- `icon?`: an optional path to override the `icon` field of the manifest
+- `screenshots?`: and optional array of path to override the `screenshots`
+ field of the manifest
#### Status codes
-* 201 Created, when the version has been successfully added to the registry
-* 409 Conflict, when the version already exists
-* 404 Not Found, when the application does not exist
-* 412 Precondition Failed, when the sent application data is invalid (could not
- fetch data URL, bad checksum, bad manifest in the tarball...)
-* 400 Bad request, when the request is invalid (bad checksum encoding, bad
- URL...)
+- 201 Created, when the version has been successfully added to the registry
+- 409 Conflict, when the version already exists
+- 404 Not Found, when the application does not exist
+- 412 Precondition Failed, when the sent application data is invalid (could
+ not fetch data URL, bad checksum, bad manifest in the tarball...)
+- 400 Bad request, when the request is invalid (bad checksum encoding, bad
+ URL...)
#### Request
@@ -243,9 +253,9 @@ Authorization: Token AbCdE
```json
{
- "version": "3.1.2",
- "url": "https://github.com/cozy/cozy-drive/archive/v3.1.2.tar.gz",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f"
+ "version": "3.1.2",
+ "url": "https://github.com/cozy/cozy-drive/archive/v3.1.2.tar.gz",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f"
}
```
@@ -258,10 +268,9 @@ Authorization: Token AbCdE
```json
{
- "version": "3.1.2-dev.7a1618dff78ba445650f266bbe334cbc9176f03a",
- "url":
- "https://github.com/cozy/cozy-photos-v3/archive/7a1618dff78ba445650f266bbe334cbc9176f03a.zip",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f"
+ "version": "3.1.2-dev.7a1618dff78ba445650f266bbe334cbc9176f03a",
+ "url": "https://github.com/cozy/cozy-photos-v3/archive/7a1618dff78ba445650f266bbe334cbc9176f03a.zip",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f"
}
```
@@ -274,11 +283,10 @@ Authorization: Token AbCdE
```json
{
- "version": "3.1.2",
- "url":
- "https://github.com/cozy/cozy-photos-v3/archive/7a1618dff78ba445650f266bbe334cbc9176f03a.zip",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "parameters": { "foo": "bar", "baz": 123 }
+ "version": "3.1.2",
+ "url": "https://github.com/cozy/cozy-photos-v3/archive/7a1618dff78ba445650f266bbe334cbc9176f03a.zip",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "parameters": { "foo": "bar", "baz": 123 }
}
```
@@ -292,16 +300,16 @@ Location: http://.../3.1.2
```json
{
- "slug": "drive",
- "type": "webapp",
- "version": "3.1.2-dev.7a1618dff78ba445650f266bbe334cbc9176f03a",
- "created_at": "2017-07-05T07:54:40.982Z",
- "url": "http://.../7a1618dff78ba445650f266bbe334cbc9176f03a.zip",
- "size": "1000",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "manifest": {
- /* ... */
- }
+ "slug": "drive",
+ "type": "webapp",
+ "version": "3.1.2-dev.7a1618dff78ba445650f266bbe334cbc9176f03a",
+ "created_at": "2017-07-05T07:54:40.982Z",
+ "url": "http://.../7a1618dff78ba445650f266bbe334cbc9176f03a.zip",
+ "size": "1000",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "manifest": {
+ /* ... */
+ }
}
```
@@ -320,10 +328,10 @@ The `filter[???]` query parameters can be used to filter by fields values.
Filtering is allowed on the following fields:
-* `type`
-* `editor`
-* `category`
-* `tags`
+- `type`
+- `editor`
+- `category`
+- `tags`
Filtering is allowed on multiple tags with the `,` separator. For example:
`filter[tags]=foo,bar` will match the applications with both `foo` and `bar` as
@@ -331,12 +339,12 @@ tags.
Sorting is allowed on the following fields:
-* `slug`
-* `type`
-* `editor`
-* `category`
-* `created_at`
-* `updated_at`
+- `slug`
+- `type`
+- `editor`
+- `category`
+- `created_at`
+- `updated_at`
#### Query-String
@@ -363,37 +371,37 @@ Content-Type: application/json
```json
{
- "data": [
- {
- "slug": "drive",
- "type": "webapp",
- "editor": "cozy",
- "versions": {
- "stable": ["3.1.1"],
- "beta": ["3.1.1-beta.1"],
- "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"]
- },
- "latest_version": {
- "slug": "drive",
- "type": "webapp",
- "version": "3.1.1",
- "url": "http://.../3.1.1",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "size": "1000",
- "created_at": "2017-07-05T07:54:40.982Z",
- "manifest": {
- /* ... */
+ "data": [
+ {
+ "slug": "drive",
+ "type": "webapp",
+ "editor": "cozy",
+ "versions": {
+ "stable": ["3.1.1"],
+ "beta": ["3.1.1-beta.1"],
+ "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"]
+ },
+ "latest_version": {
+ "slug": "drive",
+ "type": "webapp",
+ "version": "3.1.1",
+ "url": "http://.../3.1.1",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "size": "1000",
+ "created_at": "2017-07-05T07:54:40.982Z",
+ "manifest": {
+ /* ... */
+ }
+ }
+ },
+ {
+ // ...
}
- },
- },
- {
- // ...
+ ],
+ "meta": {
+ "count": 2,
+ "next_cursor": "..."
}
- ],
- "meta": {
- "count": 2,
- "next_cursor": "..."
- }
}
```
@@ -416,25 +424,25 @@ Content-Type: application/json
```json
{
- "slug": "drive",
- "editor": "cozy",
- "latest_version": {
"slug": "drive",
- "type": "webapp",
- "version": "3.1.1",
- "url": "http://.../3.1.1",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "size": "1000",
- "created_at": "2017-07-05T07:54:40.982Z",
- "manifest": {
- /* ... */
+ "editor": "cozy",
+ "latest_version": {
+ "slug": "drive",
+ "type": "webapp",
+ "version": "3.1.1",
+ "url": "http://.../3.1.1",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "size": "1000",
+ "created_at": "2017-07-05T07:54:40.982Z",
+ "manifest": {
+ /* ... */
+ }
+ },
+ "versions": {
+ "stable": ["3.1.1"],
+ "beta": ["3.1.1-beta.1"],
+ "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"]
}
- },
- "versions": {
- "stable": ["3.1.1"],
- "beta": ["3.1.1-beta.1"],
- "dev": ["3.1.1-dev.7a8354f74b50d7beead7719252a18ed45f55d070"]
- }
}
```
@@ -498,16 +506,16 @@ Content-Type: application/json
```json
{
- "slug": "drive",
- "type": "webapp",
- "version": "3.1.1",
- "url": "http://.../3.1.1",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "size": "1000",
- "created_at": "2017-07-05T07:54:40.982Z",
- "manifest": {
- /* ... */
- }
+ "slug": "drive",
+ "type": "webapp",
+ "version": "3.1.1",
+ "url": "http://.../3.1.1",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "size": "1000",
+ "created_at": "2017-07-05T07:54:40.982Z",
+ "manifest": {
+ /* ... */
+ }
}
```
@@ -530,16 +538,16 @@ Content-Type: application/json
```json
{
- "slug": "drive",
- "type": "webapp",
- "version": "3.1.1",
- "url": "http://.../3.1.1",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "size": "1000",
- "created_at": "2017-07-05T07:54:40.982Z",
- "manifest": {
- /* ... */
- }
+ "slug": "drive",
+ "type": "webapp",
+ "version": "3.1.1",
+ "url": "http://.../3.1.1",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "size": "1000",
+ "created_at": "2017-07-05T07:54:40.982Z",
+ "manifest": {
+ /* ... */
+ }
}
```
@@ -562,24 +570,24 @@ Content-Type: application/json
```json
[
- {
- "slug": "drive",
- "type": "webapp",
- "version": "3.1.1",
- "url": "http://.../3.1.1",
- "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
- "size": "1000",
- "created_at": "2017-07-05T07:54:40.982Z",
- "manifest": {
- /* ... */
- },
- "maintenance_activated": true,
- "maintenance_options": {
- "flag_infra_maintenance": true,
- "flag_short_maintenance": false,
- "flag_disallow_manual_exec": true
+ {
+ "slug": "drive",
+ "type": "webapp",
+ "version": "3.1.1",
+ "url": "http://.../3.1.1",
+ "sha256": "466aa0815926fdbf33fda523af2b9bf34520906ffbb9bf512ddf20df2992a46f",
+ "size": "1000",
+ "created_at": "2017-07-05T07:54:40.982Z",
+ "manifest": {
+ /* ... */
+ },
+ "maintenance_activated": true,
+ "maintenance_options": {
+ "flag_infra_maintenance": true,
+ "flag_short_maintenance": false,
+ "flag_disallow_manual_exec": true
+ }
}
- }
]
```
@@ -600,8 +608,8 @@ different contexts. The `default` context is applied lastly.
```yaml
registries:
- - https://myregistry.home/
- - https://main.registry.cozy.io/
+ - https://myregistry.home/
+ - https://main.registry.cozy.io/
```
```yaml
@@ -614,15 +622,15 @@ registries:
#
registries:
- context1:
- - https://context1.registry.cozy.io/
+ context1:
+ - https://context1.registry.cozy.io/
- context2:
- - https://context2.registry.cozy.io/
+ context2:
+ - https://context2.registry.cozy.io/
- default:
- - https://myregistry.home/
- - https://registry.cozy.io/
+ default:
+ - https://myregistry.home/
+ - https://registry.cozy.io/
```
# Authentication
diff --git a/docs/release.md b/docs/release.md
index 31c62f45664..02603b07ce8 100644
--- a/docs/release.md
+++ b/docs/release.md
@@ -23,30 +23,31 @@ the following format:
Where:
-* ``: closest annotated tag of the current working directory. If no tag is
- present, is uses the string "v0". This is not allowed in a production release.
-* ``: number of commits after the closest tag if
- the current working directory does not point exactly to a tag
-* `dirty`: added if the working if the working-directory is not clean (contains
- un-commited modifications). This is not allowed in production release.
-* `dev`: added for a development mode release
+- ``: closest annotated tag of the current working directory. If no tag
+ is present, is uses the string "v0". This is not allowed in a production
+ release.
+- ``: number of commits after the closest tag if
+ the current working directory does not point exactly to a tag
+- `dirty`: added if the working if the working-directory is not clean
+ (contains un-commited modifications). This is not allowed in production
+ release.
+- `dev`: added for a development mode release
# Sprint release
At the end of a sprint, we release different versions of the stack:
- - "Naked" stack, for GNU/Linux amd64/arm and FreeBSD amd64
- - Create a tag `yyyyMmSs` and push it
- - Generate all binaries, checksums and signatures with `./scripts/release.sh`
- - Create a GitHub release and upload all previously generated assets with `./scripts/release.rb`
-
- - Docker development image
- - Copy `cozy-stack` GNU/Linux amd64 binary to `./scripts`
- - Go into `./scripts`
- - Generate docker image with `docker build -t cozy/cozy-app-dev:`
- - Push image to the Docker hub with `docker push cozy/cozy-app-dev:`
-
- - Debian self-hosting packages
- - Create a new version `yyyyMmSs-1` on https://github.com/cozy/debian-cozy/blob/master/changelog
- - Create and push a tag `yyyyMmSs-1` on `https://github.com/cozy/debian-cozy`
- - Build and publish packages on our internal build machine
+- "Naked" stack, for GNU/Linux amd64/arm, FreeBSD amd64 & Docker
+
+ - Create a tag `yyyyMmSs` and push it
+ - Generate all binaries, checksums, Docker images and signatures with
+ `./scripts/release.sh`
+ - Create a GitHub release and upload all previously generated assets with
+ `./scripts/release.rb`
+
+- Debian self-hosting packages
+ - Create a new version `yyyyMmSs-1` on
+ https://github.com/cozy/debian-cozy/blob/master/changelog
+ - Create and push a tag `yyyyMmSs-1` on
+ `https://github.com/cozy/debian-cozy`
+ - Build and publish packages on our internal build machine
diff --git a/docs/remote.md b/docs/remote.md
index c9587da90f0..7377a09bcdb 100644
--- a/docs/remote.md
+++ b/docs/remote.md
@@ -51,9 +51,9 @@ Here, we have two remote doctypes. Each one has a request defined for it.
The format for the request file is:
-* the verb and the URL on the first line
-* then some lines that describe the HTTP headers
-* then a blank line and the body if the request is a POST
+- the verb and the URL on the first line
+- then some lines that describe the HTTP headers
+- then a blank line and the body if the request is a POST
For the path, the query-string, the headers, and the body, it's possible to have
some dynamic part by using `{{`, a variable name, and `}}`.
@@ -64,10 +64,10 @@ the body part of the template.
Available helpers:
-* `json`: for json parts (`{ "key": "{{json val}}" }`)
-* `html`: for html parts (`{{html val}}
`)
-* `query`: for query parameter of a url (`http://foobar.com?q={{query q}}`)
-* `path`: for path component of a url (`http://foobar.com/{{path p}}`)
+- `json`: for json parts (`{ "key": "{{json val}}" }`)
+- `html`: for html parts (`{{html val}}
`)
+- `query`: for query parameter of a url (`http://foobar.com?q={{query q}}`)
+- `path`: for path component of a url (`http://foobar.com/{{path p}}`)
Values injected in the URL are automatically URI-escaped based on the part they
are included in: namely as a query parameter or as a path component.
@@ -94,18 +94,17 @@ doctypes in its manifest, like for other doctypes:
```json
{
- "...": "...",
- "permissions": {
- "search": {
- "description": "Required for searching on wikidata",
- "type": "org.wikidata.search"
- },
- "entity": {
- "description":
- "Required for getting more informations about an entity on wikidata",
- "type": "org.wikidata.entity"
+ "...": "...",
+ "permissions": {
+ "search": {
+ "description": "Required for searching on wikidata",
+ "type": "org.wikidata.search"
+ },
+ "entity": {
+ "description": "Required for getting more informations about an entity on wikidata",
+ "type": "org.wikidata.entity"
+ }
}
- }
}
```
@@ -138,8 +137,8 @@ Content-Type: application/json
```json
{
- "query": "Qbhtynf Nqnzf",
- "comment": "query is rot13 for Douglas Adams"
+ "query": "Qbhtynf Nqnzf",
+ "comment": "query is rot13 for Douglas Adams"
}
```
@@ -150,8 +149,8 @@ something we want to allow).
### GET `/remote/assets/:asset-name`
-The client application can fetch a list of predefined assets via this route.
-The resources available are defined in the configuration file.
+The client application can fetch a list of predefined assets via this route. The
+resources available are defined in the configuration file.
Example:
diff --git a/docs/replication.md b/docs/replication.md
index 6558b637ca7..2381db828ef 100644
--- a/docs/replication.md
+++ b/docs/replication.md
@@ -5,11 +5,11 @@
Replication is the ability of a cozy-stack to copy / move all or a subset of its
data to another support. It should cover 2 use cases
-* Devices: The continuous act of syncing change to a subset of the cozy
- documents and files to and from an user cozy to the same user's Devices
- through cozy-desktop and cozy-mobile
-* Sharing: The continuous act of syncing change to a subset of the cozy
- documents and files to and from another user's cozy.
+- Devices: The continuous act of syncing change to a subset of the cozy
+ documents and files to and from an user cozy to the same user's Devices
+ through cozy-desktop and cozy-mobile
+- Sharing: The continuous act of syncing change to a subset of the cozy
+ documents and files to and from another user's cozy.
Replication will not be used for Moving, nor Backup. See associated docs in this
folder.
@@ -62,49 +62,50 @@ Repeat 2-5 until there is no more changes.
### Details
-* In step 5, the replicator can also attempt to `PUT :target/:docid` if doc are
- too heavy, but this should not happens in cozy-stack considering there wont be
- attachment in couchdb.
-* In step 4, the replicator can optimize by calling `GET`
-* The main difference from couchdb 1.X is in the replication history and the
- manner to determine and store the last sequence number. **TODO:** actually
- understand this and how it might increase disk usage if we have a lot of
- replications.
-* Couchdb `_changes` and by extension replication can be either by polling or
- continuous (SSE / COMET)
-* In couchdb benchmarking, we understood that the number of couch databases only
- use a bit of disk space but no RAM or CPU **as long as the database is not
- used**. Having a continuous replication active force us to keep the database
- file open and will starve RAM & FD usage. Moreover, continuous replication
- costs a lot (cf. ScienceTeam benchmark). To permit an unlimited number of
- inactive user on a single cozy-stack process, **the stack should avoid
- continuous replication from couchdb**.
-* Two way replication is simply two one way replications
+- In step 5, the replicator can also attempt to `PUT :target/:docid` if doc
+ are too heavy, but this should not happens in cozy-stack considering there
+ wont be attachment in couchdb.
+- In step 4, the replicator can optimize by calling `GET`
+- The main difference from couchdb 1.X is in the replication history and the
+ manner to determine and store the last sequence number. **TODO:** actually
+ understand this and how it might increase disk usage if we have a lot of
+ replications.
+- Couchdb `_changes` and by extension replication can be either by polling or
+ continuous (SSE / COMET)
+- In couchdb benchmarking, we understood that the number of couch databases
+ only use a bit of disk space but no RAM or CPU **as long as the database is
+ not used**. Having a continuous replication active force us to keep the
+ database file open and will starve RAM & FD usage. Moreover, continuous
+ replication costs a lot (cf. ScienceTeam benchmark). To permit an unlimited
+ number of inactive user on a single cozy-stack process, **the stack should
+ avoid continuous replication from couchdb**.
+- Two way replication is simply two one way replications
### Routes used by replication
To be a source of replication, the stack only need to support the following
route (and query parameters):
-* `GET :source/:docid` get revisions of a document. The query parameters
- `open_revs, revs, latest` is necessary for replication.
-* `POST :source/_all_docs` is used by current version of cozy-mobile and pouchdb
- as an optimization to fetch several document's revision at once.
-* `GET :source/_changes` get a list of ID -> New Revision since a given sequence
- number. The query parameters `since, limit` are necessary for replication.
+- `GET :source/:docid` get revisions of a document. The query parameters
+ `open_revs, revs, latest` is necessary for replication.
+- `POST :source/_all_docs` is used by current version of cozy-mobile and
+ pouchdb as an optimization to fetch several document's revision at once.
+- `GET :source/_changes` get a list of ID -> New Revision since a given
+ sequence number. The query parameters `since, limit` are necessary for
+ replication.
To be a target of replication, the stack need to support the following routes:
-* `POST :target/_revs_diff` takes a list of ID -> Rev and returns which one are
- missing.
-* `POST :target/_bulk_docs` create several documents at once
-* `POST :target/_ensure_full_commit` ensure the documents are written to disk.
- This is useless if couchdb is configured without delayed write (default), but
- remote couchdb will call, so the stack should return the expected 201
+- `POST :target/_revs_diff` takes a list of ID -> Rev and returns which one
+ are missing.
+- `POST :target/_bulk_docs` create several documents at once
+- `POST :target/_ensure_full_commit` ensure the documents are written to disk.
+ This is useless if couchdb is configured without delayed write (default),
+ but remote couchdb will call, so the stack should return the expected 201
In both case, we need to support
-* `PUT :both/_local/:revdocid` to store the current sequence number.
+- `PUT :both/_local/:revdocid` to store the current sequence number.
## Stack Sync API exploration
@@ -121,18 +122,19 @@ db.replicate.to("https://bob.cozycloud.cc/data/contacts");
To suport this we need to:
-* Proxy `/data/:doctype/_changes` route with since, limit, feed=normal. Refuse
- all filter parameters with a clear error message.
- [(Doc)](http://docs.couchdb.org/en/stable/api/database/changes.html)
-* Add support of `open_revs`, `revs`, `latest` query parameter to `GET /data/:doctype/:docid`
- [(Doc) ](http://docs.couchdb.org/en/stable/api/document/common.html?highlight=open_revs#get--db-docid)
-* Proxy the `/data/:doctype/_revs_diff`
- [(Doc)](http://docs.couchdb.org/en/stable/api/database/misc.html#db-revs-diff)
- and `/data/:doctype/_bulk_docs` routes
- [(Doc)](http://docs.couchdb.org/en/stable/api/database/bulk-api.html) routes
-* Have `/data/:doctype/_ensure_full_commit`
- [(Doc)](http://docs.couchdb.org/en/stable/api/database/compact.html#db-ensure-full-,
- revs, latestcommit) returns 201
+- Proxy `/data/:doctype/_changes` route with since, limit, feed=normal. Refuse
+ all filter parameters with a clear error message.
+ [(Doc)](http://docs.couchdb.org/en/stable/api/database/changes.html)
+- Add support of `open_revs`, `revs`, `latest` query parameter to
+ `GET /data/:doctype/:docid`
+ [(Doc) ](http://docs.couchdb.org/en/stable/api/document/common.html?highlight=open_revs#get--db-docid)
+- Proxy the `/data/:doctype/_revs_diff`
+ [(Doc)](http://docs.couchdb.org/en/stable/api/database/misc.html#db-revs-diff)
+ and `/data/:doctype/_bulk_docs` routes
+ [(Doc)](http://docs.couchdb.org/en/stable/api/database/bulk-api.html) routes
+- Have `/data/:doctype/_ensure_full_commit`
+ [(Doc)](http://docs.couchdb.org/en/stable/api/database/compact.html#db-ensure-full-,
+ revs, latestcommit) returns 201
This will cover documents part of the Devices use case.
@@ -168,10 +170,10 @@ html5-sse-example). SSE is not widely available and has some limitations
Depending on benchmarking, we can do some optimization on the feed:
-* close feeds when the user is not on screen
-* multiplex different applications' feed, so each open cozy will only use one
- socket to the server. This is hard, as all apps live on separate domain, an
- (hackish) option might be a iframe/SharedWorker bridge.
+- close feeds when the user is not on screen
+- multiplex different applications' feed, so each open cozy will only use one
+ socket to the server. This is hard, as all apps live on separate domain, an
+ (hackish) option might be a iframe/SharedWorker bridge.
To have some form of couchdb-to-stack continuous changes monitoring, we can
monitor `_db_udpates`
@@ -191,27 +193,27 @@ To be completed by discussing with Science team.
Current ideas (as understood by Romain)
-* any filtered replication is unscalable
-* 1 db for all shared docs `sharing_db`.
-* Cozy-stack is responsible for saving documents that should be shared in both
- their dg implemented by 2-way replication between the 2 users `sharing_db`,
- filtering is done by computing a list of IDs and then `doc_ids` (sharing with
- filters/views are not efficient)
-* Sharing is performed by batches regularly.
-* Continuous replication can be considered for collaborative editing.
+- any filtered replication is unscalable
+- 1 db for all shared docs `sharing_db`.
+- Cozy-stack is responsible for saving documents that should be shared in both
+ their dg implemented by 2-way replication between the 2 users `sharing_db`,
+ filtering is done by computing a list of IDs and then `doc_ids` (sharing
+ with filters/views are not efficient)
+- Sharing is performed by batches regularly.
+- Continuous replication can be considered for collaborative editing.
Proposal by Romain, if we find `_selector` filter replication performances to be
acceptable on very large / very old databases.
-* No sharing database
-* A permission, for anything is a mango-style selector.
-* on every query, the Mango selector is checked at the stack or couchdb level
- (`$and`-ing for queries, testing output document, input document)
-* Sharing is a filtered replication between user's 1 doctypedb et user's 2
- samedoctypedb
-* No continuous replication
-* Upon update, the stack trigger a PUSH replication to its remote or "ping" the
- remote, and the remote perform a normal PULL replication.
+- No sharing database
+- A permission, for anything is a mango-style selector.
+- on every query, the Mango selector is checked at the stack or couchdb level
+ (`$and`-ing for queries, testing output document, input document)
+- Sharing is a filtered replication between user's 1 doctypedb et user's 2
+ samedoctypedb
+- No continuous replication
+- Upon update, the stack trigger a PUSH replication to its remote or "ping"
+ the remote, and the remote perform a normal PULL replication.
**TODO** experiment with performance of `_selector` filtered replication in
couchdb2
diff --git a/docs/security.md b/docs/security.md
index 2453cb7a048..86dc7d239e1 100644
--- a/docs/security.md
+++ b/docs/security.md
@@ -45,11 +45,11 @@ hopefully prevent a full breach.
All the requests to the cozy stack have a strict access control. It is based on
several informations:
-* Is the user connected?
-* What is the application that makes this request?
-* What are the permissions for this application?
-* Which grant is used, in particular for applications with public pages?
-* What are the permissions for this grant?
+- Is the user connected?
+- What is the application that makes this request?
+- What are the permissions for this application?
+- Which grant is used, in particular for applications with public pages?
+- What are the permissions for this grant?
More informations [here](apps.md).
@@ -57,12 +57,12 @@ More informations [here](apps.md).
This is mostly applying the state of the art:
-* Using HTTPS, with HSTS.
-* Using secure, httpOnly,
- [sameSite](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00)
- cookies to avoid cookies theft or misuse.
-* Using a Content Security Policy (CSP).
-* Using X-frame-options http header to protect against click-jacking.
+- Using HTTPS, with HSTS.
+- Using secure, httpOnly,
+ [sameSite](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00)
+ cookies to avoid cookies theft or misuse.
+- Using a Content Security Policy (CSP).
+- Using X-frame-options http header to protect against click-jacking.
But we will use a CSP very restrictive by default (no access to other web
domains for example).
@@ -82,14 +82,14 @@ bugs.
Some data are encrypted before being saved in CouchDB (passwords for the
accounts for example). Encrypting everything has some downsides:
-* It's not possible to index encryped documents or do computations on the
- encrypted fields in reasonable time
- ([homomorphic encryption](https://en.wikipedia.org/wiki/Homomorphic_encryption)
- is still an open subject).
-* Having more encrypted data can globally weaken the encryption, if it's not
- handled properly.
-* If the encryption key is lost or a bug happen, the data is lost with no way to
- recover them.
+- It's not possible to index encryped documents or do computations on the
+ encrypted fields in reasonable time
+ ([homomorphic encryption](https://en.wikipedia.org/wiki/Homomorphic_encryption)
+ is still an open subject).
+- Having more encrypted data can globally weaken the encryption, if it's not
+ handled properly.
+- If the encryption key is lost or a bug happen, the data is lost with no way
+ to recover them.
So, we are more confortable to encrypt only some fields. And later, when we will
have more experience and feedbacks from the user, extend the encryption to more
@@ -131,9 +131,9 @@ of security weaknesses in Cozy. We will respond in less than 72 hours.
When a security flaw is found, the process is the following:
-* Make a pull-request to fix (on our private git instance) and test it.
-* Deploy the fix on cozycloud.cc
-* Publish a new version, announce it on
- [the forum](https://forum.cozy.io/c/latest-information-about-cozy-security) as
- a security update and on the mailing-lists.
-* 15 days later, add the details on the forum.
+- Make a pull-request to fix (on our private git instance) and test it.
+- Deploy the fix on cozycloud.cc
+- Publish a new version, announce it on
+ [the forum](https://forum.cozy.io/c/latest-information-about-cozy-security)
+ as a security update and on the mailing-lists.
+- 15 days later, add the details on the forum.
diff --git a/docs/settings.md b/docs/settings.md
index 4338dcae50a..8bad7ca23ce 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -27,15 +27,15 @@ Content-type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.settings",
- "id": "io.cozy.settings.disk-usage",
- "attributes": {
- "is_limited": true,
- "quota": "123456789",
- "used": "12345678"
+ "data": {
+ "type": "io.cozy.settings",
+ "id": "io.cozy.settings.disk-usage",
+ "attributes": {
+ "is_limited": true,
+ "quota": "123456789",
+ "used": "12345678"
+ }
}
- }
}
```
@@ -56,8 +56,8 @@ Content-Type: application/json
```json
{
- "register_token": "37cddf40d7724988860fa0e03efd30fe",
- "passphrase": "ThisIsTheNewShinnyPassphraseChoosedByAlice"
+ "register_token": "37cddf40d7724988860fa0e03efd30fe",
+ "passphrase": "ThisIsTheNewShinnyPassphraseChoosedByAlice"
}
```
@@ -86,8 +86,8 @@ Cookie: cozysessid=AAAAAFhSXT81MWU0ZTBiMzllMmI1OGUyMmZiN2Q0YTYzNDAxN2Y5NjCmp2Ja5
```json
{
- "current_passphrase": "ThisIsTheNewShinnyPassphraseChoosedByAlice",
- "new_passphrase": "AliceHasChangedHerPassphraseAndThisIsTheNewPassphrase"
+ "current_passphrase": "ThisIsTheNewShinnyPassphraseChoosedByAlice",
+ "new_passphrase": "AliceHasChangedHerPassphraseAndThisIsTheNewPassphrase"
}
```
@@ -114,7 +114,7 @@ Cookie: cozysessid=AAAAAFhSXT81MWU0ZTBiMzllMmI1OGUyMmZiN2Q0YTYzNDAxN2Y5NjCmp2Ja5
```json
{
- "current_passphrase": "ThisIsTheNewShinnyPassphraseChoosedByAlice"
+ "current_passphrase": "ThisIsTheNewShinnyPassphraseChoosedByAlice"
}
```
@@ -127,16 +127,14 @@ Set-Cookie: cozysessid=AAAAShoo3uo1Maic4VibuGohlik2eKUyMmZiN2Q0YTYzNDAxN2Y5NjCmp
```json
{
- "two_factor_token": "YxOSUjxd0SNmuwEEDRHXfw=="
+ "two_factor_token": "YxOSUjxd0SNmuwEEDRHXfw=="
}
```
-At this point, the current passphrase has been exchanged against a token, and
-a passcode should have been sent to the user to authenticate on the second
-step.
+At this point, the current passphrase has been exchanged against a token, and a
+passcode should have been sent to the user to authenticate on the second step.
-The token/passcode pair can be used on the second step to update the
-passphrase.
+The token/passcode pair can be used on the second step to update the passphrase.
#### Request (second step)
@@ -149,9 +147,9 @@ Cookie: cozysessid=AAAAAFhSXT81MWU0ZTBiMzllMmI1OGUyMmZiN2Q0YTYzNDAxN2Y5NjCmp2Ja5
```json
{
- "new_passphrase": "AliceHasChangedHerPassphraseAndThisIsTheNewPassphrase",
- "two_factor_token": "YxOSUjxd0SNmuwEEDRHXfw==",
- "two_factor_passcode": "4947178"
+ "new_passphrase": "AliceHasChangedHerPassphraseAndThisIsTheNewPassphrase",
+ "two_factor_token": "YxOSUjxd0SNmuwEEDRHXfw==",
+ "two_factor_passcode": "4947178"
}
```
@@ -188,20 +186,20 @@ Cookie: sessionid=xxxx
```json
{
- "data": {
- "type": "io.cozy.settings",
- "id": "io.cozy.settings.instance",
- "meta": {
- "rev": "3-56521545485448482"
- },
- "attributes": {
- "locale": "fr",
- "auto_update": true,
- "email": "alice@example.com",
- "public_name": "Alice Martin",
- "auth_mode": "basic"
+ "data": {
+ "type": "io.cozy.settings",
+ "id": "io.cozy.settings.instance",
+ "meta": {
+ "rev": "3-56521545485448482"
+ },
+ "attributes": {
+ "locale": "fr",
+ "auto_update": true,
+ "email": "alice@example.com",
+ "public_name": "Alice Martin",
+ "auth_mode": "basic"
+ }
}
- }
}
```
@@ -227,20 +225,20 @@ Authorization: Bearer settings-token
```json
{
- "data": {
- "type": "io.cozy.settings",
- "id": "io.cozy.settings.instance",
- "meta": {
- "rev": "3-56521545485448482"
- },
- "attributes": {
- "locale": "fr",
- "email": "alice@example.com",
- "public_name": "Alice Martin",
- "timezone": "Europe/Berlin",
- "auth_mode": "two_factor_mail"
+ "data": {
+ "type": "io.cozy.settings",
+ "id": "io.cozy.settings.instance",
+ "meta": {
+ "rev": "3-56521545485448482"
+ },
+ "attributes": {
+ "locale": "fr",
+ "email": "alice@example.com",
+ "public_name": "Alice Martin",
+ "timezone": "Europe/Berlin",
+ "auth_mode": "two_factor_mail"
+ }
}
- }
}
```
@@ -253,20 +251,20 @@ Content-type: application/json
```json
{
- "data": {
- "type": "io.cozy.settings",
- "id": "io.cozy.settings.instance",
- "meta": {
- "rev": "4-5a3e315e"
- },
- "attributes": {
- "locale": "fr",
- "email": "alice@example.com",
- "public_name": "Alice Martin",
- "timezone": "Europe/Berlin",
- "auth_mode": "two_factor_mail"
+ "data": {
+ "type": "io.cozy.settings",
+ "id": "io.cozy.settings.instance",
+ "meta": {
+ "rev": "4-5a3e315e"
+ },
+ "attributes": {
+ "locale": "fr",
+ "email": "alice@example.com",
+ "public_name": "Alice Martin",
+ "timezone": "Europe/Berlin",
+ "auth_mode": "two_factor_mail"
+ }
}
- }
}
```
@@ -277,32 +275,33 @@ To use this endpoint, an application needs a permission on the type
### PUT /settings/instance/auth_mode
-With this route, the user can ask for the activation of different
-authentication modes, like two-factor authentication.
+With this route, the user can ask for the activation of different authentication
+modes, like two-factor authentication.
Available authentication modes:
-* `basic`: basic authentication only with passphrase
-* `two_factor_mail`: authentication with passphrase and validation with a
- code sent via email to the user.
+- `basic`: basic authentication only with passphrase
+- `two_factor_mail`: authentication with passphrase and validation with a code
+ sent via email to the user.
When asking for activation of the two-factor authentication, a side-effect can
be triggered to send the user its code (via email for instance), and the
-activation not being effective. This side-effect should provide the user with
-a code that can be used to finalize the activation of the two-factor
+activation not being effective. This side-effect should provide the user with a
+code that can be used to finalize the activation of the two-factor
authentication.
Hence, this route has two behaviors:
-* the code is not provided: the route is a side effect to ask for the
- activation of 2FA, and a code is sent
-* the code is provided, and valid: the two-factor authentication is actually
- activated.
+- the code is not provided: the route is a side effect to ask for the
+ activation of 2FA, and a code is sent
+- the code is provided, and valid: the two-factor authentication is actually
+ activated.
Status codes:
-* `204 No Content`: when the mail has been confirmed and two-factor authentication is activated
-* `422 Unprocessable Entity`: when the given confirmation code is not good.
+- `204 No Content`: when the mail has been confirmed and two-factor
+ authentication is activated
+- `422 Unprocessable Entity`: when the given confirmation code is not good.
#### Request
@@ -315,8 +314,8 @@ Cookie: cozysessid=AAAAAFhSXT81MWU0ZTBiMzllMmI1OGUyMmZiN2Q0YTYzNDAxN2Y5NjCmp2Ja5
```json
{
- "auth_mode": "two_factor_mail",
- "two_factor_activation_code": "12345678"
+ "auth_mode": "two_factor_mail",
+ "two_factor_activation_code": "12345678"
}
```
@@ -326,7 +325,8 @@ With this route, an OAuth client can sign the new TOS version.
Status codes:
-* `204 No Content`: when the mail has been confirmed and two-factor authentication is activated
+- `204 No Content`: when the mail has been confirmed and two-factor
+ authentication is activated
#### Request
@@ -355,17 +355,17 @@ Content-Type: application/json
```json
{
- "data": [
- {
- "id": "...",
- "attributes": {
- "last_seen": ""
- },
- "meta": {
- "rev": "..."
- }
- }
- ]
+ "data": [
+ {
+ "id": "...",
+ "attributes": {
+ "last_seen": ""
+ },
+ "meta": {
+ "rev": "..."
+ }
+ }
+ ]
}
```
@@ -399,26 +399,26 @@ Content-type: application/json
```json
{
- "data": [
- {
- "type": "io.cozy.oauth.clients",
- "id": "30e84c10-e6cf-11e6-9bfd-a7106972de51",
- "attributes": {
- "redirect_uris": ["http://localhost:4000/oauth/callback"],
- "client_name": "Cozy-Desktop on my-new-laptop",
- "client_kind": "desktop",
- "client_uri": "https://docs.cozy.io/en/mobile/desktop.html",
- "logo_uri": "https://docs.cozy.io/assets/images/cozy-logo-docs.svg",
- "policy_uri": "https://cozy.io/policy",
- "software_id": "/github.com/cozy-labs/cozy-desktop",
- "software_version": "0.16.0",
- "synchronized_at": "2017-09-05T16:23:04Z"
- },
- "links": {
- "self": "/settings/clients/30e84c10-e6cf-11e6-9bfd-a7106972de51"
- }
- }
- ]
+ "data": [
+ {
+ "type": "io.cozy.oauth.clients",
+ "id": "30e84c10-e6cf-11e6-9bfd-a7106972de51",
+ "attributes": {
+ "redirect_uris": ["http://localhost:4000/oauth/callback"],
+ "client_name": "Cozy-Desktop on my-new-laptop",
+ "client_kind": "desktop",
+ "client_uri": "https://docs.cozy.io/en/mobile/desktop.html",
+ "logo_uri": "https://docs.cozy.io/assets/images/cozy-logo-docs.svg",
+ "policy_uri": "https://cozy.io/policy",
+ "software_id": "/github.com/cozy-labs/cozy-desktop",
+ "software_version": "0.16.0",
+ "synchronized_at": "2017-09-05T16:23:04Z"
+ },
+ "links": {
+ "self": "/settings/clients/30e84c10-e6cf-11e6-9bfd-a7106972de51"
+ }
+ }
+ ]
}
```
@@ -493,18 +493,18 @@ Cookie: sessionid=xxxx
```json
{
- "data": {
- "type": "io.cozy.settings",
- "id": "io.cozy.settings.context",
- "attributes": {
- "default_redirection": "drive/#/files",
- "help_link": "https://forum.cozy.io/",
- "onboarded_redirection": "collect/#/discovery/?intro"
- },
- "links": {
- "self": "/settings/context"
+ "data": {
+ "type": "io.cozy.settings",
+ "id": "io.cozy.settings.context",
+ "attributes": {
+ "default_redirection": "drive/#/files",
+ "help_link": "https://forum.cozy.io/",
+ "onboarded_redirection": "collect/#/discovery/?intro"
+ },
+ "links": {
+ "self": "/settings/context"
+ }
}
- }
}
```
diff --git a/docs/sharing-design.md b/docs/sharing-design.md
index 87726d9ebef..f651a038385 100644
--- a/docs/sharing-design.md
+++ b/docs/sharing-design.md
@@ -4,9 +4,9 @@
1. A sharer may not know the adresses of the recipients' cozy instances, but
he/she has a way to send them an URL on his/her cozy to start the process.
-2. A user can preview a sharing before accepting it if the application
- supports this option. Else, he/she will have only the description and rules to
- make his/her mind about accepting or refusing the sharing.
+2. A user can preview a sharing before accepting it if the application supports
+ this option. Else, he/she will have only the description and rules to make
+ his/her mind about accepting or refusing the sharing.
3. The data is duplicated: it is both on the owner's cozy, and on the
recipients' cozy (no cloud federation like NextCloud).
4. The applications say what is shared, the stack synchronizes that. The stack
@@ -27,8 +27,8 @@
documents that were on the user B's cozy before the sharing are not sent to
user A without an explicit action of user B (like moving a file to a shared
directory).
-10. Second safety principle: when two users, A and B, are sharing documents,
- a change of a document on the user A's cozy can't make an exiting document of
+10. Second safety principle: when two users, A and B, are sharing documents, a
+ change of a document on the user A's cozy can't make an exiting document of
user B enter in the sharing.
## Setup of a sharing
@@ -57,16 +57,16 @@ Alice’s instance the answer.
### Step 3: the initial replication starts
-Alice’s Cozy instance creates token and sends them with other informations as the
-response of the answer request from Bob’s instance. At this moment, both
+Alice’s Cozy instance creates token and sends them with other informations as
+the response of the answer request from Bob’s instance. At this moment, both
instances are ready to start to replicate data to the other instances. So, let’s
do the initial replication.
Alice’s instance starts to fill the `io.cozy.shared` database with all the
-documents that match a rule of the sharing (except the rules with `local:
-true`), and create triggers for the future documents to be also added in this
-database (the exact triggers depend of the parameters of the rules). And, when
-done, it creates a job for the replicator, and setups a trigger for future
+documents that match a rule of the sharing (except the rules with
+`local: true`), and create triggers for the future documents to be also added in
+this database (the exact triggers depend of the parameters of the rules). And,
+when done, it creates a job for the replicator, and setups a trigger for future
changes in the `io.cozy.shared` start a replicator job.
Bob’s instance also checks if any document matches a sharing rule. In most
@@ -93,18 +93,18 @@ start a replicator
**Step 3:** the replicator does the following steps
-* it queries a local document of the `io.cozy.shared` database to get the last
- sequence number of a successful replication
-* with this sequence number, it requests the changes feed of `io.cozy.shared`
- with a filter on the sharing id
-* the results is a list of document doctype + id + rev that is sent to Alice’s
- Cozy
-* Alice’s Cozy checks which revisions are known, and send a response with the
- list of those that are not
-* for each not known revision, Bob’s Cozy send the document to Alice’s Cozy (in
- bulk)
-* and, if it’s all good, it persists the new sequence number in the local
- document, as a start point for the next replication
+- it queries a local document of the `io.cozy.shared` database to get the last
+ sequence number of a successful replication
+- with this sequence number, it requests the changes feed of `io.cozy.shared`
+ with a filter on the sharing id
+- the results is a list of document doctype + id + rev that is sent to Alice’s
+ Cozy
+- Alice’s Cozy checks which revisions are known, and send a response with the
+ list of those that are not
+- for each not known revision, Bob’s Cozy send the document to Alice’s Cozy
+ (in bulk)
+- and, if it’s all good, it persists the new sequence number in the local
+ document, as a start point for the next replication
**Step 4:** the changes are put in the `io.cozy.shared` database on Alice’s Cozy
@@ -206,9 +206,9 @@ emptied.
When a file is modified concurrently on two cozy instances, and at least one
change involve the content, we can't reconciliate the modifications. To know
-which version of the file is the "winner" and will keep the same identifier,
-and which version is the "loser" and will have a new identifier, we compare
-the revisions and the higher wins.
+which version of the file is the "winner" and will keep the same identifier, and
+which version is the "loser" and will have a new identifier, we compare the
+revisions and the higher wins.
This conflict is particulary tricky to resolve, with a lot of subcases. In
particular, we try to converge to the same revisions on all the instances for
@@ -216,21 +216,21 @@ the "winner" file (and for the "loser" too).
We have 3 sets of attributes for files:
-- `size` and `md5sum` (they change when the content has changed)
-- `name` and `dir_id` (they change when the file is moved or renamed)
-- `created_at`, `updated_at`, `tags`, `referenced_by`, etc.
+- `size` and `md5sum` (they change when the content has changed)
+- `name` and `dir_id` (they change when the file is moved or renamed)
+- `created_at`, `updated_at`, `tags`, `referenced_by`, etc.
For the first two sets, the operation on the Virtual File System will needs to
reach the storage (Swift), not just CouchDB. For the third set, it's easy: we
can do the change at the same time as another change, because these attributes
-are only used in CouchDB. But we can't do a change on the first two sets at
-the same time: the Virtual File System can't update the content and
-move/rename a file in the same operation. If we needs to do both, it will
-generate 2 revisions in CouchDB for the file.
-
-**Note:** you can see that using CouchDB-like replication protocol means that
-we have some replications that can look useless, just some echo to a writing.
-In fact, it is used to acknowledge the writing and is helpful for conflict
+are only used in CouchDB. But we can't do a change on the first two sets at the
+same time: the Virtual File System can't update the content and move/rename a
+file in the same operation. If we needs to do both, it will generate 2 revisions
+in CouchDB for the file.
+
+**Note:** you can see that using CouchDB-like replication protocol means that we
+have some replications that can look useless, just some echo to a writing. In
+fact, it is used to acknowledge the writing and is helpful for conflict
resolutions. It may be conter-intuitive, but removing them will harm the
stability of the system, even if they do nothing most of the time.
@@ -253,131 +253,138 @@ on B because the local revision (4-4bb) is greater than the candidate revision
(4-4aa) and the content is the same.
Just after that, we have a revision on the opposite direction (from Bob to
-Alice). The candidate revision wins (4-4bb), but for files, we don't use
-CouchDB conflict, thus it's not possible to write a new revision at the same
-generation (4). The only option is to create a new revision (5-5bb). This
-revision is then sent to Bob: Bob's Cozy accepts the new revision even if it
-has no effect on the file (it was already the good name), just to resolve the
-conflict.
+Alice). The candidate revision wins (4-4bb), but for files, we don't use CouchDB
+conflict, thus it's not possible to write a new revision at the same generation
+(4). The only option is to create a new revision (5-5bb). This revision is then
+sent to Bob: Bob's Cozy accepts the new revision even if it has no effect on the
+file (it was already the good name), just to resolve the conflict.
#### Example 2

-Like in the last example, Alice uploads a file and share a directory to Bob
-with this file, Bob acccepts. But then, several actions are made on the file in
-a short lapse of time and it generates a difficult conflict:
+Like in the last example, Alice uploads a file and share a directory to Bob with
+this file, Bob acccepts. But then, several actions are made on the file in a
+short lapse of time and it generates a difficult conflict:
-- Alice renames the file, and then uploads a new version with cozy-desktop
-- Bob moves the file to a sub-directory.
+- Alice renames the file, and then uploads a new version with cozy-desktop
+- Bob moves the file to a sub-directory.
-So, when the replication comes, we have two versions of the file with
-different name, parent directory, and content. The winner is the higher
-revision (4-4aa). The resolution takes 4 steps:
+So, when the replication comes, we have two versions of the file with different
+name, parent directory, and content. The winner is the higher revision (4-4aa).
+The resolution takes 4 steps:
1. A copy of the file is created from the revision 3-3bb, with the new
identifier id2 = XorID(id, 3-3bb).
2. The new content is written on Bob's Cozy: we can't use the revisions 3-3aa
- (same generation as 3-3bb) and 4-4aa (it will mean the conflict is fixed,
- but it's not the case, the filenames are still different), so a new
- revision is used (4-4cc).
+ (same generation as 3-3bb) and 4-4aa (it will mean the conflict is fixed, but
+ it's not the case, the filenames are still different), so a new revision is
+ used (4-4cc).
3. The file is moved and renamed on Bob's Cozy, with a next revision (5-5bb).
-4. The two files are sent to Alice's Cozy: 5-5bb is accepted just to resolve
- the conflict, and id2 is uploaded as a new file.
-
+4. The two files are sent to Alice's Cozy: 5-5bb is accepted just to resolve the
+ conflict, and id2 is uploaded as a new file.
## Schema
### Description of a sharing
-* An identifier (the same for all members of the sharing)
-* A list of `members`. The first one is the owner. For each member,
- we have the URL of the cozy, a contact name, a public name, an email, a
- status, a read-only flag, and some credentials to authorize the transfer of
- data between the owner and the recipients
-* A `description` (one sentence that will help people understand what is shared
- and why)
-- a flag `active` that says if the sharing is currently active for at least
- one member
-- a flag `owner`, true for the document on the cozy of the sharer, and false
- on the other cozy instance
-* a flag `open_sharing`:
- * `true` if any member of the sharing except the read-only ones can add a
- new recipient
- * `false` if only the owner can add a new recipient
-* Some technical data (`created_at`, `updated_at`, `app_slug`, `preview_path`,
- `triggers`, `credentials`)
-* a number of files to synchronize for the initial sync,
- `initial_number_of_files_to_sync` (if there are no files to sync or the
- initial replication has finished, the field won't be here)
-* A list of sharing `rules`, each rule being composed of:
- * a `title`, that will be displayed to the recipients before they accept the
- sharing
- * a `doctype`
- * a `selector` (by default, it’s the `id`) and `values` (one identifier, a
- list of identifiers, files and folders inside a folder, files that are
- referenced by the same document, documents bound to a previous sharing rule)
- * `local`: by default `false`, but it can be `true` for documents that are
- useful for the preview page but doesn’t need to be send to the recipients
- (e.g. a setting document of the application)
- * `add`: a behavior when a new document matches this rule (the document is
- created, or it was a document that didn’t match the rule and is modified and
- the new version matches the rule):
- * `none`: the updates are never propagated (the default)
- * `push`: the updates made on the owner are sent to the recipients
- * `sync`: the updates on any member (except the read-only) are propagated to the other members
- * `update`: a behavior when a document matched by this rule is modified. Can be:
- * `none`: the updates are never propagated (the default)
- * `push`: the updates made on the owner are sent to the recipients
- * `sync`: the updates on any member (except the read-only) are propagated to the other members
- * `remove`: a behavior when a document no longer matches this rule (the
- document is deleted, or it was a document that matched the rule, and is
- modified and the new version doesn’t match the rule):
- * `none`: the updates are never propagated (the default)
- * `push`: the updates made on the owner are sent to the recipients
- * `sync`: the updates on any member (except the read-only) are propagated to the other members
- * `revoke`: the sharing is revoked.
+- An identifier (the same for all members of the sharing)
+- A list of `members`. The first one is the owner. For each member, we have
+ the URL of the cozy, a contact name, a public name, an email, a status, a
+ read-only flag, and some credentials to authorize the transfer of data
+ between the owner and the recipients
+- A `description` (one sentence that will help people understand what is
+ shared and why)
+
+* a flag `active` that says if the sharing is currently active for at least
+ one member
+* a flag `owner`, true for the document on the cozy of the sharer, and false
+ on the other cozy instance
+
+- a flag `open_sharing`:
+ - `true` if any member of the sharing except the read-only ones can add a
+ new recipient
+ - `false` if only the owner can add a new recipient
+- Some technical data (`created_at`, `updated_at`, `app_slug`, `preview_path`,
+ `triggers`, `credentials`)
+- a number of files to synchronize for the initial sync,
+ `initial_number_of_files_to_sync` (if there are no files to sync or the
+ initial replication has finished, the field won't be here)
+- A list of sharing `rules`, each rule being composed of:
+ - a `title`, that will be displayed to the recipients before they accept
+ the sharing
+ - a `doctype`
+ - a `selector` (by default, it’s the `id`) and `values` (one identifier, a
+ list of identifiers, files and folders inside a folder, files that are
+ referenced by the same document, documents bound to a previous sharing
+ rule)
+ - `local`: by default `false`, but it can be `true` for documents that are
+ useful for the preview page but doesn’t need to be send to the
+ recipients (e.g. a setting document of the application)
+ - `add`: a behavior when a new document matches this rule (the document is
+ created, or it was a document that didn’t match the rule and is modified
+ and the new version matches the rule):
+ - `none`: the updates are never propagated (the default)
+ - `push`: the updates made on the owner are sent to the recipients
+ - `sync`: the updates on any member (except the read-only) are
+ propagated to the other members
+ - `update`: a behavior when a document matched by this rule is modified.
+ Can be:
+ - `none`: the updates are never propagated (the default)
+ - `push`: the updates made on the owner are sent to the recipients
+ - `sync`: the updates on any member (except the read-only) are
+ propagated to the other members
+ - `remove`: a behavior when a document no longer matches this rule (the
+ document is deleted, or it was a document that matched the rule, and is
+ modified and the new version doesn’t match the rule):
+ - `none`: the updates are never propagated (the default)
+ - `push`: the updates made on the owner are sent to the recipients
+ - `sync`: the updates on any member (except the read-only) are
+ propagated to the other members
+ - `revoke`: the sharing is revoked.
#### Example: I want to share a folder in read/write mode
-* rule 1
- * title: `folder`
- * doctype: `io.cozy.files`
- * values: `"ca527016-0d83-11e8-a580-3b965c80c7f7"`
- * add: `sync`
- * update: `sync`
- * remove: `sync`
+- rule 1
+ - title: `folder`
+ - doctype: `io.cozy.files`
+ - values: `"ca527016-0d83-11e8-a580-3b965c80c7f7"`
+ - add: `sync`
+ - update: `sync`
+ - remove: `sync`
#### Example: I want to share a playlist where I’m the only one that can add and remove items
-* rule 1
- * title: `playlist`
- * doctype: `io.cozy.music.playlists`
- * values: `"99445b14-0d84-11e8-ae72-4b96fcbf0552"`
- * update: `none`
- * remove: `revoke`
-* rule 2
- * title: `items`
- * doctype: `io.cozy.files`
- * selector: `referenced_by`
- * values: `"io.cozy.files/ca527016-0d83-11e8-a580-3b965c80c7f7"`
- * add: `push`
- * update: `none`
- * remove: `push`
+- rule 1
+ - title: `playlist`
+ - doctype: `io.cozy.music.playlists`
+ - values: `"99445b14-0d84-11e8-ae72-4b96fcbf0552"`
+ - update: `none`
+ - remove: `revoke`
+- rule 2
+ - title: `items`
+ - doctype: `io.cozy.files`
+ - selector: `referenced_by`
+ - values: `"io.cozy.files/ca527016-0d83-11e8-a580-3b965c80c7f7"`
+ - add: `push`
+ - update: `none`
+ - remove: `push`
### `io.cozy.shared`
This doctype is an internal one for the stack. It is used to track what
documents are shared, and to replicate changes from one Cozy to the others.
-* `_id`: its identifier is the doctype and id of the referenced objet, separated by
- a `/` (e.g. `io.cozy.contacts/c1f5dae4-0d87-11e8-b91b-1f41c005768b`)
-* `_rev`: the CouchDB default revision for this document (not very meaningful,
- it’s here to avoid concurrency issues)
-* `revisions`: a tree with the last known `_rev`s of the referenced object
-* `infos`, a map of sharing ids → `{rule, removed, binary}`
- * `rule` says which rule from the sharing must be applied for this document
- * `removed` will be true for a deleted document, a trashed file, or if the
- document does no longer match the sharing rule
- * `binary` is a boolean flag that is true only for files (and not even
- folders) with `removed: false`
+- `_id`: its identifier is the doctype and id of the referenced objet,
+ separated by a `/` (e.g.
+ `io.cozy.contacts/c1f5dae4-0d87-11e8-b91b-1f41c005768b`)
+- `_rev`: the CouchDB default revision for this document (not very meaningful,
+ it’s here to avoid concurrency issues)
+- `revisions`: a tree with the last known `_rev`s of the referenced object
+- `infos`, a map of sharing ids → `{rule, removed, binary}`
+ - `rule` says which rule from the sharing must be applied for this
+ document
+ - `removed` will be true for a deleted document, a trashed file, or if the
+ document does no longer match the sharing rule
+ - `binary` is a boolean flag that is true only for files (and not even
+ folders) with `removed: false`
diff --git a/docs/sharing.md b/docs/sharing.md
index 1dee7fd167a..8b109387e34 100644
--- a/docs/sharing.md
+++ b/docs/sharing.md
@@ -37,12 +37,12 @@ users.
### Intents
When a sharing is authorized, the user is redirected to their cozy on the
-application that was used for the sharing (when possible). It's possible to
-use a specific route to do so, via the intents. The application must declare
-an intent in its manifest for the action `SHARING`. The doctype of the intent
-must be the same as the doctype of the first rule of the sharing. In the
-redirect URL, the query string will have a `sharing` parameter with the
-sharing ID (but no intent parameter).
+application that was used for the sharing (when possible). It's possible to use
+a specific route to do so, via the intents. The application must declare an
+intent in its manifest for the action `SHARING`. The doctype of the intent must
+be the same as the doctype of the first rule of the sharing. In the redirect
+URL, the query string will have a `sharing` parameter with the sharing ID (but
+no intent parameter).
### Routes
@@ -53,8 +53,7 @@ Create a new sharing. The sharing rules and recipients must be specified. The
`app_slug` field is optional and is the slug of the web app by default.
To create a sharing, no permissions on `io.cozy.sharings` are needed: an
-application can create a sharing on the documents for whose it has a
-permission.
+application can create a sharing on the documents for whose it has a permission.
##### Request
@@ -66,33 +65,33 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "attributes": {
- "description": "sharing test",
- "preview_path": "/preview-sharing",
- "rules": [
- {
- "title": "Hawaii",
- "doctype": "io.cozy.files",
- "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
+ "data": {
+ "type": "io.cozy.sharings",
+ "attributes": {
+ "description": "sharing test",
+ "preview_path": "/preview-sharing",
+ "rules": [
+ {
+ "title": "Hawaii",
+ "doctype": "io.cozy.files",
+ "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
+ },
+ "relationships": {
+ "recipients": {
+ "data": [
+ {
+ "id": "2a31ce0128b5f89e40fd90da3f014087",
+ "type": "io.cozy.contacts"
+ }
+ ]
+ }
}
- ]
- },
- "relationships": {
- "recipients": {
- "data": [
- {
- "id": "2a31ce0128b5f89e40fd90da3f014087",
- "type": "io.cozy.contacts"
- }
- ]
- }
}
- }
}
```
@@ -105,47 +104,47 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "meta": {
- "rev": "1-4859c6c755143adf0838d225c5e97882"
- },
- "attributes": {
- "description": "sharing test",
- "preview_path": "/preview-sharing",
- "app_slug": "drive",
- "owner": true,
- "created_at": "2018-01-04T12:35:08Z",
- "updated_at": "2018-01-04T13:45:43Z",
- "members": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
+ "data": {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "meta": {
+ "rev": "1-4859c6c755143adf0838d225c5e97882"
},
- {
- "status": "mail-not-sent",
- "name": "Bob",
- "email": "bob@example.net"
- }
- ],
- "rules": [
- {
- "title": "Hawaii",
- "doctype": "io.cozy.files",
- "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
+ "attributes": {
+ "description": "sharing test",
+ "preview_path": "/preview-sharing",
+ "app_slug": "drive",
+ "owner": true,
+ "created_at": "2018-01-04T12:35:08Z",
+ "updated_at": "2018-01-04T13:45:43Z",
+ "members": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "mail-not-sent",
+ "name": "Bob",
+ "email": "bob@example.net"
+ }
+ ],
+ "rules": [
+ {
+ "title": "Hawaii",
+ "doctype": "io.cozy.files",
+ "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
+ },
+ "links": {
+ "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- ]
- },
- "links": {
- "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- }
}
```
@@ -204,15 +203,15 @@ Location: https://bob.example.net/auth/sharing?...
#### JSON
-This version can be more convenient for applications that implement the
-preview page. To do that, an application must give a `preview_path` when
-creating the sharing. This path must be a public route of this application.
-The recipients will receive a link to the application subdomain, on this page,
-and with a `sharecode` in the query string (like for a share by link).
+This version can be more convenient for applications that implement the preview
+page. To do that, an application must give a `preview_path` when creating the
+sharing. This path must be a public route of this application. The recipients
+will receive a link to the application subdomain, on this page, and with a
+`sharecode` in the query string (like for a share by link).
-To know the `sharing-id`, it's possible to ask `GET /permissions/self`, with
-the `sharecode` in the `Authorization` header (it's a JWT token). In the
-response, the `source_id` field will be `io.cozy.sharings/`.
+To know the `sharing-id`, it's possible to ask `GET /permissions/self`, with the
+`sharecode` in the `Authorization` header (it's a JWT token). In the response,
+the `source_id` field will be `io.cozy.sharings/`.
##### Parameters
@@ -239,32 +238,32 @@ Content-Type: application/json
```json
{
- "redirect": "https://bob.example.net/auth/sharing?..."
+ "redirect": "https://bob.example.net/auth/sharing?..."
}
```
### GET /sharings/:sharing-id
-Get the information about a sharing. This includes the content of the rules,
-the members, as well as the already shared documents for this sharing.
+Get the information about a sharing. This includes the content of the rules, the
+members, as well as the already shared documents for this sharing.
For a member, we can have the following fields:
-- a contact name (`name`), that is the name of this user as it appears in its
- contact document (if there is one such document)
-- a public name (`public_name`), that is the name this user has put on his
- cozy as a public name (it is used for sending emails for example)
-- an email addresse (`email`)
-- an instance URL (`instance`)
-- and a status (`status`).
+- a contact name (`name`), that is the name of this user as it appears in its
+ contact document (if there is one such document)
+- a public name (`public_name`), that is the name this user has put on his
+ cozy as a public name (it is used for sending emails for example)
+- an email addresse (`email`)
+- an instance URL (`instance`)
+- and a status (`status`).
**Notes:**
-- the first member is always the sharer
-- to display the list of members to a user, the `name` should be use if
- available, and if it is not the case, you can use the `public_name` or the
- `email`
-- on a recipient, the only member with an `instance` is the local user.
+- the first member is always the sharer
+- to display the list of members to a user, the `name` should be use if
+ available, and if it is not the case, you can use the `public_name` or the
+ `email`
+- on a recipient, the only member with an `instance` is the local user.
#### Request
@@ -283,62 +282,62 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "meta": {
- "rev": "1-4859c6c755143adf0838d225c5e97882"
- },
- "attributes": {
- "description": "sharing test",
- "preview_path": "/preview-sharing",
- "app_slug": "drive",
- "owner": true,
- "created_at": "2018-01-04T12:35:08Z",
- "updated_at": "2018-01-04T13:45:43Z",
- "initial_number_of_files_to_sync": 42,
- "members": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
+ "data": {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "meta": {
+ "rev": "1-4859c6c755143adf0838d225c5e97882"
},
- {
- "status": "ready",
- "name": "Bob",
- "email": "bob@example.net"
- }
- ],
- "rules": [
- {
- "title": "Hawaii",
- "doctype": "io.cozy.files",
- "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
+ "attributes": {
+ "description": "sharing test",
+ "preview_path": "/preview-sharing",
+ "app_slug": "drive",
+ "owner": true,
+ "created_at": "2018-01-04T12:35:08Z",
+ "updated_at": "2018-01-04T13:45:43Z",
+ "initial_number_of_files_to_sync": 42,
+ "members": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "ready",
+ "name": "Bob",
+ "email": "bob@example.net"
+ }
+ ],
+ "rules": [
+ {
+ "title": "Hawaii",
+ "doctype": "io.cozy.files",
+ "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
+ },
+ "relationships": {
+ "shared_docs": {
+ "data": [
+ {
+ "id": "612acf1c-1d72-11e8-b043-ef239d3074dd",
+ "type": "io.cozy.files"
+ },
+ {
+ "id": "a34528d2-13fb-9482-8d20-bf1972531225",
+ "type": "io.cozy.files"
+ }
+ ]
+ }
+ },
+ "links": {
+ "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- ]
- },
- "relationships": {
- "shared_docs": {
- "data": [
- {
- "id": "612acf1c-1d72-11e8-b043-ef239d3074dd",
- "type": "io.cozy.files"
- },
- {
- "id": "a34528d2-13fb-9482-8d20-bf1972531225",
- "type": "io.cozy.files"
- }
- ]
- }
- },
- "links": {
- "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- }
}
```
@@ -365,117 +364,117 @@ Content-Type: application/vnd.api+json
```json
{
- "data": [
- {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "attributes": {
- "description": "sharing test",
- "preview_path": "/preview-sharing",
- "app_slug": "drive",
- "owner": true,
- "created_at": "2018-01-04T12:35:08Z",
- "updated_at": "2018-01-04T13:45:43Z",
- "members": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
- },
- {
- "status": "ready",
- "name": "Bob",
- "email": "bob@example.net"
- }
- ],
- "rules": [
- {
- "title": "Hawaii",
- "doctype": "io.cozy.files",
- "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
- }
- ]
- },
- "meta": {
- "rev": "1-4859c6c755143adf0838d225c5e97882"
- },
- "links": {
- "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
- },
- "relationships": {
- "shared_docs": {
- "data": [
- {
- "id": "612acf1c-1d72-11e8-b043-ef239d3074dd",
- "type": "io.cozy.files"
+ "data": [
+ {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "attributes": {
+ "description": "sharing test",
+ "preview_path": "/preview-sharing",
+ "app_slug": "drive",
+ "owner": true,
+ "created_at": "2018-01-04T12:35:08Z",
+ "updated_at": "2018-01-04T13:45:43Z",
+ "members": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "ready",
+ "name": "Bob",
+ "email": "bob@example.net"
+ }
+ ],
+ "rules": [
+ {
+ "title": "Hawaii",
+ "doctype": "io.cozy.files",
+ "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
+ },
+ "meta": {
+ "rev": "1-4859c6c755143adf0838d225c5e97882"
+ },
+ "links": {
+ "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
},
- {
- "id": "a34528d2-13fb-9482-8d20-bf1972531225",
- "type": "io.cozy.files"
+ "relationships": {
+ "shared_docs": {
+ "data": [
+ {
+ "id": "612acf1c-1d72-11e8-b043-ef239d3074dd",
+ "type": "io.cozy.files"
+ },
+ {
+ "id": "a34528d2-13fb-9482-8d20-bf1972531225",
+ "type": "io.cozy.files"
+ }
+ ]
+ }
}
- ]
- }
- }
- },
- {
- "type": "io.cozy.sharings",
- "id": "b4e58d039c03d01742085de5e505284e",
- "attributes": {
- "description": "another sharing test",
- "preview_path": "/preview-sharing",
- "app_slug": "drive",
- "owner": true,
- "created_at": "2018-02-04T12:35:08Z",
- "updated_at": "2018-02-04T13:45:43Z",
- "members": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
- },
- {
- "status": "ready",
- "name": "Bob",
- "email": "bob@example.net"
- }
- ],
- "rules": [
- {
- "title": "Singapore",
- "doctype": "io.cozy.files",
- "values": ["e18e30e2-8eda-1bde-afce-edafc6b1a91b"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
- }
- ]
- },
- "meta": {
- "rev": "1-7ac5f1252a0c513186a5d35b1a6fd350"
- },
- "links": {
- "self": "/sharings/b4e58d039c03d01742085de5e505284e"
- },
- "relationships": {
- "shared_docs": {
- "data": [
- {
- "id": "dcc52bee-1277-a6b3-b36f-369ffd81a4ee",
- "type": "io.cozy.files"
+ },
+ {
+ "type": "io.cozy.sharings",
+ "id": "b4e58d039c03d01742085de5e505284e",
+ "attributes": {
+ "description": "another sharing test",
+ "preview_path": "/preview-sharing",
+ "app_slug": "drive",
+ "owner": true,
+ "created_at": "2018-02-04T12:35:08Z",
+ "updated_at": "2018-02-04T13:45:43Z",
+ "members": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "ready",
+ "name": "Bob",
+ "email": "bob@example.net"
+ }
+ ],
+ "rules": [
+ {
+ "title": "Singapore",
+ "doctype": "io.cozy.files",
+ "values": ["e18e30e2-8eda-1bde-afce-edafc6b1a91b"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
+ },
+ "meta": {
+ "rev": "1-7ac5f1252a0c513186a5d35b1a6fd350"
+ },
+ "links": {
+ "self": "/sharings/b4e58d039c03d01742085de5e505284e"
+ },
+ "relationships": {
+ "shared_docs": {
+ "data": [
+ {
+ "id": "dcc52bee-1277-a6b3-b36f-369ffd81a4ee",
+ "type": "io.cozy.files"
+ }
+ ]
+ }
}
- ]
}
- }
+ ],
+ "meta": {
+ "count": 3
}
- ],
- "meta": {
- "count": 3
- }
}
```
@@ -483,8 +482,8 @@ Content-Type: application/vnd.api+json
The sharer's cozy sends a request to this route on the recipient's cozy to
create a sharing request, with most of the information about the sharing. This
-request will be displayed to the recipient just before its final acceptation
-of the sharing, to be sure he/she knows what will be shared.
+request will be displayed to the recipient just before its final acceptation of
+the sharing, to be sure he/she knows what will be shared.
#### Request
@@ -496,41 +495,41 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "attributes": {
- "description": "sharing test",
- "preview_path": "/preview-sharing",
- "app_slug": "drive",
- "owner": true,
- "created_at": "2018-01-04T12:35:08Z",
- "updated_at": "2018-01-04T13:45:43Z",
- "members": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
- },
- {
- "status": "mail-not-sent",
- "email": "bob@example.net",
- "instance": "bob.example.net"
- }
- ],
- "rules": [
- {
- "title": "Hawaii",
- "doctype": "io.cozy.files",
- "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
+ "data": {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "attributes": {
+ "description": "sharing test",
+ "preview_path": "/preview-sharing",
+ "app_slug": "drive",
+ "owner": true,
+ "created_at": "2018-01-04T12:35:08Z",
+ "updated_at": "2018-01-04T13:45:43Z",
+ "members": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "mail-not-sent",
+ "email": "bob@example.net",
+ "instance": "bob.example.net"
+ }
+ ],
+ "rules": [
+ {
+ "title": "Hawaii",
+ "doctype": "io.cozy.files",
+ "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
}
- ]
}
- }
}
```
@@ -543,48 +542,48 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "meta": {
- "rev": "1-f579a69a9fa5dd720010a1dbb82320be"
- },
- "attributes": {
- "description": "sharing test",
- "preview_path": "/preview-sharing",
- "app_slug": "drive",
- "owner": true,
- "created_at": "2018-01-04T12:35:08Z",
- "updated_at": "2018-01-04T13:45:43Z",
- "members": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
+ "data": {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "meta": {
+ "rev": "1-f579a69a9fa5dd720010a1dbb82320be"
},
- {
- "status": "mail-not-sent",
- "name": "Bob",
- "email": "bob@example.net",
- "instance": "bob.example.net"
- }
- ],
- "rules": [
- {
- "title": "Hawaii",
- "doctype": "io.cozy.files",
- "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
+ "attributes": {
+ "description": "sharing test",
+ "preview_path": "/preview-sharing",
+ "app_slug": "drive",
+ "owner": true,
+ "created_at": "2018-01-04T12:35:08Z",
+ "updated_at": "2018-01-04T13:45:43Z",
+ "members": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "mail-not-sent",
+ "name": "Bob",
+ "email": "bob@example.net",
+ "instance": "bob.example.net"
+ }
+ ],
+ "rules": [
+ {
+ "title": "Hawaii",
+ "doctype": "io.cozy.files",
+ "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
+ },
+ "links": {
+ "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- ]
- },
- "links": {
- "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- }
}
```
@@ -638,8 +637,8 @@ Content-Type: application/vnd.api+json
### POST /sharings/:sharing-id/recipients
-This route allows the sharer to add new recipients to a sharing. It can also
-be used by a recipient when the sharing has `open_sharing` set to true if the
+This route allows the sharer to add new recipients to a sharing. It can also be
+used by a recipient when the sharing has `open_sharing` set to true if the
recipient doesn't have the `read_only` flag
#### Request
@@ -652,28 +651,28 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "relationships": {
- "recipients": {
- "data": [
- {
- "id": "ce7b1dfbd460039159f228298a29b2aa",
- "type": "io.cozy.contacts",
- }
- ]
- },
- "read_only_recipients": {
- "data": [
- {
- "id": "e15384a1223ae2501cc1c4fa94008ea0",
- "type": "io.cozy.contacts",
- }
- ]
- }
+ "data": {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "relationships": {
+ "recipients": {
+ "data": [
+ {
+ "id": "ce7b1dfbd460039159f228298a29b2aa",
+ "type": "io.cozy.contacts"
+ }
+ ]
+ },
+ "read_only_recipients": {
+ "data": [
+ {
+ "id": "e15384a1223ae2501cc1c4fa94008ea0",
+ "type": "io.cozy.contacts"
+ }
+ ]
+ }
+ }
}
- }
}
```
@@ -686,73 +685,73 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "meta": {
- "rev": "1-4859c6c755143adf0838d225c5e97882"
- },
- "attributes": {
- "description": "sharing test",
- "preview_path": "/preview-sharing",
- "app_slug": "drive",
- "owner": true,
- "created_at": "2018-01-04T12:35:08Z",
- "updated_at": "2018-01-04T13:45:43Z",
- "members": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
+ "data": {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "meta": {
+ "rev": "1-4859c6c755143adf0838d225c5e97882"
},
- {
- "status": "ready",
- "name": "Bob",
- "public_name": "Bob",
- "email": "bob@example.net"
+ "attributes": {
+ "description": "sharing test",
+ "preview_path": "/preview-sharing",
+ "app_slug": "drive",
+ "owner": true,
+ "created_at": "2018-01-04T12:35:08Z",
+ "updated_at": "2018-01-04T13:45:43Z",
+ "members": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "ready",
+ "name": "Bob",
+ "public_name": "Bob",
+ "email": "bob@example.net"
+ },
+ {
+ "status": "pending",
+ "name": "Charlie",
+ "email": "charlie@example.net"
+ },
+ {
+ "status": "pending",
+ "name": "Dave",
+ "email": "dave@example.net",
+ "read_only": true
+ }
+ ],
+ "rules": [
+ {
+ "title": "Hawaii",
+ "doctype": "io.cozy.files",
+ "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
+ "add": "sync",
+ "update": "sync",
+ "remove": "sync"
+ }
+ ]
},
- {
- "status": "pending",
- "name": "Charlie",
- "email": "charlie@example.net",
+ "relationships": {
+ "shared_docs": {
+ "data": [
+ {
+ "id": "612acf1c-1d72-11e8-b043-ef239d3074dd",
+ "type": "io.cozy.files"
+ },
+ {
+ "id": "a34528d2-13fb-9482-8d20-bf1972531225",
+ "type": "io.cozy.files"
+ }
+ ]
+ }
},
- {
- "status": "pending",
- "name": "Dave",
- "email": "dave@example.net",
- "read_only": true
- }
- ],
- "rules": [
- {
- "title": "Hawaii",
- "doctype": "io.cozy.files",
- "values": ["612acf1c-1d72-11e8-b043-ef239d3074dd"],
- "add": "sync",
- "update": "sync",
- "remove": "sync"
+ "links": {
+ "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- ]
- },
- "relationships": {
- "shared_docs": {
- "data": [
- {
- "id": "612acf1c-1d72-11e8-b043-ef239d3074dd",
- "type": "io.cozy.files"
- },
- {
- "id": "a34528d2-13fb-9482-8d20-bf1972531225",
- "type": "io.cozy.files"
- }
- ]
- }
- },
- "links": {
- "self": "/sharings/ce8835a061d0ef68947afe69a0046722"
}
- }
}
```
@@ -771,19 +770,19 @@ Content-Type: application/vnd.api+json
```json
{
- "data": {
- "type": "io.cozy.sharings",
- "id": "ce8835a061d0ef68947afe69a0046722",
- "relationships": {
- "recipients": {
- "data": [
- {
- "email": "dave@example.net"
- }
- ]
- }
+ "data": {
+ "type": "io.cozy.sharings",
+ "id": "ce8835a061d0ef68947afe69a0046722",
+ "relationships": {
+ "recipients": {
+ "data": [
+ {
+ "email": "dave@example.net"
+ }
+ ]
+ }
+ }
}
- }
}
```
@@ -796,7 +795,7 @@ Content-Type: application/json
```json
{
- "dave@example.net": "uS6wN7fTYaLZ-GdC_P6UWA"
+ "dave@example.net": "uS6wN7fTYaLZ-GdC_P6UWA"
}
```
@@ -815,32 +814,32 @@ Content-Type: application/vnd.api+json
```json
{
- "data": [
- {
- "status": "owner",
- "public_name": "Alice",
- "email": "alice@example.net",
- "instance": "alice.example.net"
- },
- {
- "status": "ready",
- "name": "Bob",
- "public_name": "Bob",
- "email": "bob@example.net"
- },
- {
- "status": "ready",
- "name": "Charlie",
- "public_name": "Charlie",
- "email": "charlie@example.net",
- },
- {
- "status": "pending",
- "name": "Dave",
- "email": "dave@example.net",
- "read_only": true
- }
- ]
+ "data": [
+ {
+ "status": "owner",
+ "public_name": "Alice",
+ "email": "alice@example.net",
+ "instance": "alice.example.net"
+ },
+ {
+ "status": "ready",
+ "name": "Bob",
+ "public_name": "Bob",
+ "email": "bob@example.net"
+ },
+ {
+ "status": "ready",
+ "name": "Charlie",
+ "public_name": "Charlie",
+ "email": "charlie@example.net"
+ },
+ {
+ "status": "pending",
+ "name": "Dave",
+ "email": "dave@example.net",
+ "read_only": true
+ }
+ ]
}
```
@@ -926,8 +925,8 @@ HTTP/1.1 204 No Content
### DELETE /sharings/:sharing-id/recipients/self/readonly
This is an internal route for the stack. It's used to inform the recipient's
-cozy that it is no longer in read-only mode, and to give it the credentials
-for sending its updates.
+cozy that it is no longer in read-only mode, and to give it the credentials for
+sending its updates.
#### Request
@@ -961,9 +960,9 @@ HTTP/1.1 204 No Content
This route is used by an application on the owner's cozy to revoke the sharing
for all the members. After that, the sharing active flag will be false, the
-credentials for all members will be revoked, the members that have accepted
-the sharing will have their cozy informed that the sharing has been revoked,
-and pending members can no longer accept this sharing.
+credentials for all members will be revoked, the members that have accepted the
+sharing will have their cozy informed that the sharing has been revoked, and
+pending members can no longer accept this sharing.
#### Request
@@ -980,10 +979,10 @@ HTTP/1.1 204 No Content
### DELETE /sharings/:sharing-id/recipients/:index
-This route is used to revoke only one recipient of the sharing. The parameter
-is the index of this recipient in the `members` array of the sharing. The
-status for this member will be set to `revoked`, its cozy will be informed of
-the revokation, and the credentials for this cozy will be deleted.
+This route is used to revoke only one recipient of the sharing. The parameter is
+the index of this recipient in the `members` array of the sharing. The status
+for this member will be set to `revoked`, its cozy will be informed of the
+revokation, and the credentials for this cozy will be deleted.
**Note**: 0 is not accepted for `index`, as it is the sharer him-self.
@@ -1002,8 +1001,8 @@ HTTP/1.1 204 No Content
### DELETE /sharings/:sharing-id/recipients/self
-This route can be used by an application in the cozy of a recipient to remove
-it from the sharing.
+This route can be used by an application in the cozy of a recipient to remove it
+from the sharing.
#### Request
@@ -1038,8 +1037,8 @@ HTTP/1.1 204 No Content
### DELETE /sharings/:sharing-id/answer
-This is an internal route used by a recipient's cozy to inform the owner's
-cozy that this recipient no longer wants to be part of the sharing.
+This is an internal route used by a recipient's cozy to inform the owner's cozy
+that this recipient no longer wants to be part of the sharing.
#### Request
@@ -1072,13 +1071,13 @@ Authorization: Bearer ...
```json
{
- "io.cozy.files/29631902-2cec-11e8-860d-435b24c2cc58": [
- "2-4a7e4ae49c4366eaed8edeaea8f784ad"
- ],
- "io.cozy.files/44f5752a-2cec-11e8-b227-abfc3cfd4b6e": [
- "4-2ee767305024673cfb3f5af037cd2729",
- "4-efc54218773c6acd910e2e97fea2a608"
- ]
+ "io.cozy.files/29631902-2cec-11e8-860d-435b24c2cc58": [
+ "2-4a7e4ae49c4366eaed8edeaea8f784ad"
+ ],
+ "io.cozy.files/44f5752a-2cec-11e8-b227-abfc3cfd4b6e": [
+ "4-2ee767305024673cfb3f5af037cd2729",
+ "4-efc54218773c6acd910e2e97fea2a608"
+ ]
}
```
@@ -1091,17 +1090,17 @@ Content-Type: application/json
```json
{
- "io.cozy.files/44f5752a-2cec-11e8-b227-abfc3cfd4b6e": {
- "missing": ["4-2ee767305024673cfb3f5af037cd2729"],
- "possible_ancestors": ["3-753875d51501a6b1883a9d62b4d33f91"]
- }
+ "io.cozy.files/44f5752a-2cec-11e8-b227-abfc3cfd4b6e": {
+ "missing": ["4-2ee767305024673cfb3f5af037cd2729"],
+ "possible_ancestors": ["3-753875d51501a6b1883a9d62b4d33f91"]
+ }
}
```
### POST /sharings/:sharing-id/\_bulk_docs
-This endpoint is used by the sharing replicator of the stack to send
-documents in a bulk to the other cozy. It is inspired by
+This endpoint is used by the sharing replicator of the stack to send documents
+in a bulk to the other cozy. It is inspired by
http://docs.couchdb.org/en/stable/api/database/bulk-api.html#db-bulk-docs.
**Note**: we force `new_edits` to `false`.
@@ -1118,19 +1117,19 @@ Authorization: Bearer ...
```json
{
- "io.cozy.files": [
- {
- "_id": "44f5752a-2cec-11e8-b227-abfc3cfd4b6e",
- "_rev": "4-2ee767305024673cfb3f5af037cd2729",
- "_revisions": {
- "start": 4,
- "ids": [
- "2ee767305024673cfb3f5af037cd2729",
- "753875d51501a6b1883a9d62b4d33f91"
- ]
- }
- }
- ]
+ "io.cozy.files": [
+ {
+ "_id": "44f5752a-2cec-11e8-b227-abfc3cfd4b6e",
+ "_rev": "4-2ee767305024673cfb3f5af037cd2729",
+ "_revisions": {
+ "start": 4,
+ "ids": [
+ "2ee767305024673cfb3f5af037cd2729",
+ "753875d51501a6b1883a9d62b4d33f91"
+ ]
+ }
+ }
+ ]
}
```
@@ -1147,12 +1146,11 @@ Content-Type: application/json
### GET /sharings/:sharing-id/io.cozy.files/:file-id
-This is an internal endpoint used by a stack to get information about a
-folder. It is used when a cozy sent to another cozy a file or folder inside a
-folder that was trashed (and trash was emptied): the recipient does no longer
-have information about the parent directory. To resolve the conflict, it
-recreates the missing parent directory by asking the other cozy informations
-about it.
+This is an internal endpoint used by a stack to get information about a folder.
+It is used when a cozy sent to another cozy a file or folder inside a folder
+that was trashed (and trash was emptied): the recipient does no longer have
+information about the parent directory. To resolve the conflict, it recreates
+the missing parent directory by asking the other cozy informations about it.
#### Request
@@ -1172,14 +1170,14 @@ Content-Type: application/json
```json
{
- "_id": "6d245d072be5522bd3a6f273dd000c65",
- "_rev": "1-de4ec176ffa9ddafe8bdcc739dc60fed",
- "type": "directory",
- "name": "phone",
- "dir_id": "6d245d072be5522bd3a6f273dd007396",
- "created_at": "2016-09-19T12:35:08Z",
- "updated_at": "2016-09-19T12:35:08Z",
- "tags": ["bills"]
+ "_id": "6d245d072be5522bd3a6f273dd000c65",
+ "_rev": "1-de4ec176ffa9ddafe8bdcc739dc60fed",
+ "type": "directory",
+ "name": "phone",
+ "dir_id": "6d245d072be5522bd3a6f273dd007396",
+ "created_at": "2016-09-19T12:35:08Z",
+ "updated_at": "2016-09-19T12:35:08Z",
+ "tags": ["bills"]
}
```
@@ -1200,37 +1198,36 @@ Authorization: Bearer ...
```json
{
- "_id": "4b24ab130b2538b7b444fc65430198ad",
- "_rev": "1-356bf77c03baa1da851a2be1f06aba81",
- "_revisions": {
- "start": 1,
- "ids": ["356bf77c03baa1da851a2be1f06aba81"]
- },
- "type": "file",
- "name": "cloudy.jpg",
- "dir_id": "4b24ab130b2538b7b444fc65430188cd",
- "created_at": "2018-01-03T16:10:36.885807013+01:00",
- "updated_at": "2018-01-03T16:10:36.885807013+01:00",
- "size": "84980",
- "md5sum": "SuRJOiD/QPwDUpKpQujcVA==",
- "mime": "image/jpeg",
- "class": "image",
- "executable": false,
- "trashed": false,
- "tags": [],
- "metadata": {
- "datetime": "2018-01-03T16:10:36.89118949+01:00",
- "extractor_version": 2,
- "height": 1200,
- "width": 1600
- }
+ "_id": "4b24ab130b2538b7b444fc65430198ad",
+ "_rev": "1-356bf77c03baa1da851a2be1f06aba81",
+ "_revisions": {
+ "start": 1,
+ "ids": ["356bf77c03baa1da851a2be1f06aba81"]
+ },
+ "type": "file",
+ "name": "cloudy.jpg",
+ "dir_id": "4b24ab130b2538b7b444fc65430188cd",
+ "created_at": "2018-01-03T16:10:36.885807013+01:00",
+ "updated_at": "2018-01-03T16:10:36.885807013+01:00",
+ "size": "84980",
+ "md5sum": "SuRJOiD/QPwDUpKpQujcVA==",
+ "mime": "image/jpeg",
+ "class": "image",
+ "executable": false,
+ "trashed": false,
+ "tags": [],
+ "metadata": {
+ "datetime": "2018-01-03T16:10:36.89118949+01:00",
+ "extractor_version": 2,
+ "height": 1200,
+ "width": 1600
+ }
}
```
#### Response
-If only the metadata has changed (not the content), the response will be a
-204:
+If only the metadata has changed (not the content), the response will be a 204:
```http
HTTP/1.1 204 No Content
@@ -1245,14 +1242,14 @@ Content-Type: application/json
```json
{
- "key": "dcd478c6-46cf-11e8-9c3f-535468cbce7b"
+ "key": "dcd478c6-46cf-11e8-9c3f-535468cbce7b"
}
```
### PUT /sharings/:sharing-id/io.cozy.files/:key
-Upload the content of a file (new file or its content has changed since the
-last synchronization).
+Upload the content of a file (new file or its content has changed since the last
+synchronization).
#### Request
@@ -1271,8 +1268,8 @@ HTTP/1.1 204 No Content
### DELETE /sharings/:sharing-id/initial
-This internal route is used by the sharer to inform a recipient's cozy that
-the initial sync is finished.
+This internal route is used by the sharer to inform a recipient's cozy that the
+initial sync is finished.
```http
DELETE /sharings/ce8835a061d0ef68947afe69a0046722/initial HTTP/1.1
diff --git a/docs/toc.yml b/docs/toc.yml
index 8d8379f89ba..ad8698e48b7 100644
--- a/docs/toc.yml
+++ b/docs/toc.yml
@@ -16,23 +16,25 @@
- Services:
- "/auth - Authentication & OAuth": ./auth.md
- "/apps - Applications Management": ./apps.md
- - "Apps registry": ./registry.md
+ - " /apps - Apps registry": ./registry.md
+ - " /apps - Konnectors": ./konnectors.md
+ - " /apps - Konnectors workflow": ./konnectors-workflow.md
- "/data - Data System": ./data-system.md
- - "Mango": ./mango.md
- - "Replication": ./replication.md
- - "CouchDB Quirks": ./couchdb-quirks.md
- - "PouchDB Quirks": ./pouchdb-quirks.md
+ - " /data - Mango": ./mango.md
+ - " /data - Replication": ./replication.md
+ - " /data - CouchDB Quirks": ./couchdb-quirks.md
+ - " /data - PouchDB Quirks": ./pouchdb-quirks.md
- "/files - Virtual File System": ./files.md
- - "References of documents in VFS": ./references-docs-in-vfs.md
+ - " /files - References of documents in VFS": ./references-docs-in-vfs.md
- "/intents - Intents": ./intents.md
- - "/jobs Jobs": ./jobs.md
- - "Konnectors": ./konnectors.md
- - "Workers": ./workers.md
+ - "/jobs - Jobs": ./jobs.md
+ - " /jobs - Workers": ./workers.md
- "/move - Move, export and import an instance": ./move.md
- "/notifications - Notifications": ./notifications.md
- "/permissions - Permissions": ./permissions.md
- "/realtime - Realtime": ./realtime.md
- "/remote - Proxy for remote data/API": ./remote.md
- "/settings - Settings": ./settings.md
+ - " /settings - Terms of Services": ./user-action-required.md
- "/sharings - Sharing": ./sharing.md
- - "Request for comments": ./sharing-design.md
+ - " /sharings - Request for comments": ./sharing-design.md
diff --git a/docs/user-action-required.md b/docs/user-action-required.md
index 06e27f37594..a634f01e531 100644
--- a/docs/user-action-required.md
+++ b/docs/user-action-required.md
@@ -2,14 +2,14 @@
# User action is required
-This document explains how the stack can alert applications that an user
-action is required to perform the expected services. For example, the stack
-can block most of its API until the user read and sign new terms of services.
+This document explains how the stack can alert applications that an user action
+is required to perform the expected services. For example, the stack can block
+most of its API until the user read and sign new terms of services.
## HTTP 402 Error
-In some cases the stack will return a 402 error to API requests.
-402 will be used to denote error that require an user's action.
+In some cases the stack will return a 402 error to API requests. 402 will be
+used to denote error that require an user's action.
For now, the only use case is a Terms Of Services update, but some other use
cases might appear in the future. The specific cause of this error will be
@@ -23,35 +23,36 @@ Content-Type: application/vnd.api+json
```json
{
- "errors": [
- {
- "status": "402",
- "title": "TOS Updated",
- "code": "tos-updated",
- "detail": "Terms of services have been updated",
- "links": {
- "self": "https://manager.cozycloud.cc/cozy/tos?domain=..."
- }
- }
- ]
+ "errors": [
+ {
+ "status": "402",
+ "title": "TOS Updated",
+ "code": "tos-updated",
+ "detail": "Terms of services have been updated",
+ "links": {
+ "self": "https://manager.cozycloud.cc/cozy/tos?domain=..."
+ }
+ }
+ ]
}
```
-If they receive such a code, the clients should block any further action on
-the stack, warn the user with the necessary message and provide a button
-allowing the user to perform the required action.
+If they receive such a code, the clients should block any further action on the
+stack, warn the user with the necessary message and provide a button allowing
+the user to perform the required action.
-* If the client knows the specific `error` code, display a beautiful message.
-* Otherwise, display the message provided by the stack and use the links.action on the button.
+- If the client knows the specific `error` code, display a beautiful message.
+- Otherwise, display the message provided by the stack and use the
+ links.action on the button.
-Possible other codes in the future: `payment_required` for functions requiring
-a premium account, etc.
+Possible other codes in the future: `payment_required` for functions requiring a
+premium account, etc.
# Anticipating these errors and warning the user
-An enpoints exists to get the list of warnings that the user can anticipate.
-For applications these warnings are included directly into the HTML of the
-index page, as follow:
+An enpoints exists to get the list of warnings that the user can anticipate. For
+applications these warnings are included directly into the HTML of the index
+page, as follow:
```html
0 && channel[0] == '/' {
- channel = channel[1:]
- }
- if channel == "" {
- channel = "stable"
- }
+ channel := getRegistryChannel(src)
version, err := registry.GetLatestVersion(slug, channel, f.registries)
if err != nil {
f.log.Infof("Could not fetch manifest for %s: %s", src.String(), err.Error())
@@ -55,3 +49,14 @@ func (f *registryFetcher) Fetch(src *url.URL, fs Copier, man Manifest) error {
man.SetVersion(v.Version)
return fetchHTTP(u, shasum, fs, man, v.TarPrefix)
}
+
+func getRegistryChannel(src *url.URL) string {
+ channel := src.Path
+ if len(channel) > 0 && channel[0] == '/' {
+ channel = channel[1:]
+ }
+ if channel == "" {
+ channel = "stable"
+ }
+ return channel
+}
diff --git a/pkg/apps/installer.go b/pkg/apps/installer.go
index 48f9f04e641..8f55e5eea70 100644
--- a/pkg/apps/installer.go
+++ b/pkg/apps/installer.go
@@ -11,6 +11,7 @@ import (
"github.com/cozy/cozy-stack/pkg/logger"
"github.com/cozy/cozy-stack/pkg/prefixer"
"github.com/cozy/cozy-stack/pkg/realtime"
+ "github.com/cozy/cozy-stack/pkg/registry"
"github.com/cozy/cozy-stack/pkg/utils"
"github.com/sirupsen/logrus"
)
@@ -44,7 +45,6 @@ type Installer struct {
src *url.URL
slug string
- errc chan error
manc chan Manifest
log *logrus.Entry
}
@@ -114,7 +114,22 @@ func NewInstaller(db prefixer.Prefixer, fs Copier, opts *InstallerOptions) (*Ins
endState = Ready
}
- log := logger.WithDomain(db.DomainName()).WithField("nspace", "apps")
+ var installType string
+ switch opts.Operation {
+ case Install:
+ installType = "install"
+ case Update:
+ installType = "update"
+ case Delete:
+ installType = "delete"
+ }
+
+ log := logger.WithDomain(db.DomainName()).WithFields(logrus.Fields{
+ "nspace": "apps",
+ "slug": man.Slug(),
+ "version_start": man.Version(),
+ "type": installType,
+ })
var manFilename string
switch man.AppType() {
@@ -152,7 +167,6 @@ func NewInstaller(db prefixer.Prefixer, fs Copier, opts *InstallerOptions) (*Ins
src: src,
slug: man.Slug(),
- errc: make(chan error, 1),
manc: make(chan Manifest, 2),
log: log,
}, nil
@@ -210,43 +224,44 @@ func (i *Installer) Domain() string {
// depending on specified operation. It will report its progress or error (see
// Poll method) and should be run asynchronously.
func (i *Installer) Run() {
- var err error
+ if err := i.run(); err != nil {
+ i.man.SetError(err)
+ realtime.GetHub().Publish(i.db, realtime.EventUpdate, i.man.Clone(), nil)
+ }
+ i.notifyChannel()
+}
+// RunSync does the same work as Run but can be used synchronously.
+func (i *Installer) RunSync() (Manifest, error) {
+ i.manc = nil
+ if err := i.run(); err != nil {
+ return nil, err
+ }
+ return i.man.Clone().(Manifest), nil
+}
+
+func (i *Installer) run() (err error) {
if i.man == nil {
panic("Manifest is nil")
}
-
+ defer func() {
+ if err != nil {
+ i.log.Errorf("Could not commit installer process: %s", err)
+ } else {
+ i.log.Infof("Successful installer process: %s", i.man.Version())
+ }
+ }()
+ i.log.Info("Start")
switch i.op {
case Install:
- err = i.install()
+ return i.install()
case Update:
- err = i.update()
+ return i.update()
case Delete:
- err = i.delete()
+ return i.delete()
default:
panic("Unknown operation")
}
-
- man := i.man.Clone().(Manifest)
- if err != nil {
- man.SetError(err)
- realtime.GetHub().Publish(i.db, realtime.EventUpdate, man.Clone(), nil)
- }
- i.manc <- man
-}
-
-// RunSync does the same work as Run but can be used synchronously.
-func (i *Installer) RunSync() (Manifest, error) {
- go i.Run()
- for {
- man, done, err := i.Poll()
- if err != nil {
- return nil, err
- }
- if done {
- return man, nil
- }
- }
}
// install will perform the installation of an application. It returns the
@@ -256,7 +271,6 @@ func (i *Installer) RunSync() (Manifest, error) {
// Note that the fetched manifest is returned even if an error occurred while
// upgrading.
func (i *Installer) install() error {
- i.log.Infof("Start install: %s %s", i.slug, i.src.String())
args := []string{i.db.DomainName(), i.slug}
return hooks.Execute("install-app", args, func() error {
newManifest, err := i.ReadManifest(Installing)
@@ -265,7 +279,7 @@ func (i *Installer) install() error {
}
i.man = newManifest
i.sendRealtimeEvent()
- i.manc <- i.man.Clone().(Manifest)
+ i.notifyChannel()
if err := i.fetcher.Fetch(i.src, i.fs, i.man); err != nil {
return err
}
@@ -281,7 +295,6 @@ func (i *Installer) install() error {
// Note that the fetched manifest is returned even if an error occurred while
// upgrading.
func (i *Installer) update() error {
- i.log.Infof("Start update: %s %s", i.slug, i.src.String())
if err := i.checkState(i.man); err != nil {
return err
}
@@ -299,6 +312,7 @@ func (i *Installer) update() error {
// For git:// and file:// sources, it may be more complicated since we need
// to actually fetch the data to extract the exact version of the manifest.
makeUpdate := true
+ availableVersion := ""
switch i.src.Scheme {
case "registry", "http", "https":
makeUpdate = (newManifest.Version() != oldManifest.Version())
@@ -315,28 +329,37 @@ func (i *Installer) update() error {
newPermissions.HasSameRules(oldPermissions)
if !samePermissions && !i.permissionsAcked {
makeUpdate = false
+ availableVersion = newManifest.Version()
}
}
if makeUpdate {
i.man = newManifest
i.sendRealtimeEvent()
- i.manc <- i.man.Clone().(Manifest)
+ i.notifyChannel()
if err := i.fetcher.Fetch(i.src, i.fs, i.man); err != nil {
return err
}
i.man.SetState(i.endState)
} else {
- i.man.SetAvailableVersion(newManifest.Version())
+ i.man.SetSource(i.src)
+ if availableVersion != "" {
+ i.man.SetAvailableVersion(availableVersion)
+ }
i.sendRealtimeEvent()
- i.manc <- i.man.Clone().(Manifest)
+ i.notifyChannel()
}
return i.man.Update(i.db)
}
+func (i *Installer) notifyChannel() {
+ if i.manc != nil {
+ i.manc <- i.man.Clone().(Manifest)
+ }
+}
+
func (i *Installer) delete() error {
- i.log.Infof("Start delete: %s %s", i.slug, i.src.String())
if err := i.checkState(i.man); err != nil {
return err
}
@@ -401,6 +424,34 @@ func (i *Installer) Poll() (Manifest, bool, error) {
return man, done, man.Error()
}
+func doLazyUpdate(db prefixer.Prefixer, man Manifest, availableVersion string, copier Copier, registries []*url.URL) Manifest {
+ src, err := url.Parse(man.Source())
+ if err != nil || src.Scheme != "registry" {
+ return man
+ }
+ v, errv := registry.GetLatestVersion(man.Slug(), getRegistryChannel(src), registries)
+ if errv != nil || v.Version == man.Version() {
+ return man
+ }
+ if availableVersion != "" && v.Version == availableVersion {
+ return man
+ }
+ inst, err := NewInstaller(db, copier, &InstallerOptions{
+ Operation: Update,
+ Manifest: man,
+ Registries: registries,
+ SourceURL: src.String(),
+ })
+ if err != nil {
+ return man
+ }
+ newman, err := inst.RunSync()
+ if err != nil {
+ return man
+ }
+ return newman
+}
+
func isPlatformApp(man Manifest) bool {
if man.AppType() != Webapp {
return false
diff --git a/pkg/apps/konnector.go b/pkg/apps/konnector.go
index 3a0c6e995fb..043f899d49a 100644
--- a/pkg/apps/konnector.go
+++ b/pkg/apps/konnector.go
@@ -3,6 +3,7 @@ package apps
import (
"encoding/json"
"io"
+ "net/url"
"time"
"github.com/cozy/cozy-stack/pkg/consts"
@@ -108,6 +109,9 @@ func (m *KonnManifest) SetID(id string) {}
// SetRev is part of the Manifest interface
func (m *KonnManifest) SetRev(rev string) { m.DocRev = rev }
+// SetSource is part of the Manifest interface
+func (m *KonnManifest) SetSource(src *url.URL) { m.DocSource = src.String() }
+
// Source is part of the Manifest interface
func (m *KonnManifest) Source() string { return m.DocSource }
@@ -229,6 +233,17 @@ func GetKonnectorBySlug(db prefixer.Prefixer, slug string) (*KonnManifest, error
return man, nil
}
+// GetWebappBySlugAndUpdate fetch the KonnManifest and perform an update of
+// the application if necessary and if the application was installed from the
+// registry.
+func GetKonnectorBySlugAndUpdate(db prefixer.Prefixer, slug string, copier Copier, registries []*url.URL) (*KonnManifest, error) {
+ man, err := GetKonnectorBySlug(db, slug)
+ if err != nil {
+ return nil, err
+ }
+ return doLazyUpdate(db, man, man.AvailableVersion, copier, registries).(*KonnManifest), nil
+}
+
// ListKonnectors returns the list of installed konnectors applications.
//
// TODO: pagination
diff --git a/pkg/apps/webapp.go b/pkg/apps/webapp.go
index 3c9a94828d2..76631592821 100644
--- a/pkg/apps/webapp.go
+++ b/pkg/apps/webapp.go
@@ -3,6 +3,7 @@ package apps
import (
"encoding/json"
"io"
+ "net/url"
"path"
"strings"
"time"
@@ -46,21 +47,6 @@ type Services map[string]*Service
// application.
type Notifications map[string]notification.Properties
-// Locales is a map to define the available locales of the application.
-type Locales map[string]interface{}
-
-// Developer is the name and url of a developer.
-type Developer struct {
- Name string `json:"name"`
- URL string `json:"url,omitempty"`
-}
-
-// Platform is a supported additional device platform of the application.
-type Platform struct {
- Type string `json:"type"`
- URL string `json:"url"`
-}
-
// Intent is a declaration of a service for other client-side apps
type Intent struct {
Action string `json:"action"`
@@ -170,6 +156,9 @@ func (m *WebappManifest) SetID(id string) {}
// SetRev is part of the Manifest interface
func (m *WebappManifest) SetRev(rev string) { m.DocRev = rev }
+// SetSource is part of the Manifest interface
+func (m *WebappManifest) SetSource(src *url.URL) { m.DocSource = src.String() }
+
// Source is part of the Manifest interface
func (m *WebappManifest) Source() string { return m.DocSource }
@@ -223,6 +212,20 @@ func (m *WebappManifest) Match(field, value string) bool {
return false
}
+func (m *WebappManifest) NameLocalized(locale string) string {
+ if m.Locales != nil && locale != "" {
+ var locales map[string]struct {
+ Name string `json:"name"`
+ }
+ if err := json.Unmarshal(*m.Locales, &locales); err == nil {
+ if v, ok := locales[locale]; ok && v.Name != "" {
+ return v.Name
+ }
+ }
+ }
+ return m.Name
+}
+
// ReadManifest is part of the Manifest interface
func (m *WebappManifest) ReadManifest(r io.Reader, slug, sourceURL string) (Manifest, error) {
var newManifest WebappManifest
@@ -436,6 +439,17 @@ func GetWebappBySlug(db prefixer.Prefixer, slug string) (*WebappManifest, error)
return man, nil
}
+// GetWebappBySlugAndUpdate fetch the WebappManifest and perform an update of
+// the application if necessary and if the application was installed from the
+// registry.
+func GetWebappBySlugAndUpdate(db prefixer.Prefixer, slug string, copier Copier, registries []*url.URL) (*WebappManifest, error) {
+ man, err := GetWebappBySlug(db, slug)
+ if err != nil {
+ return nil, err
+ }
+ return doLazyUpdate(db, man, man.AvailableVersion, copier, registries).(*WebappManifest), nil
+}
+
// ListWebapps returns the list of installed web applications.
//
// TODO: pagination
diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go
new file mode 100644
index 00000000000..4bfbd88fac9
--- /dev/null
+++ b/pkg/cache/cache.go
@@ -0,0 +1,65 @@
+package cache
+
+import (
+ "bytes"
+ "compress/gzip"
+ "io"
+ "time"
+
+ "github.com/go-redis/redis"
+)
+
+// Cache is a rudimentary key/value caching store backed by redis. It offers a
+// Get/Set interface as well a its gzip compressed alternative
+// GetCompressed/SetCompressed
+type Cache struct {
+ client redis.UniversalClient
+}
+
+// New returns a new Cache from a potentially nil redis client.
+func New(client redis.UniversalClient) Cache {
+ return Cache{client}
+}
+
+// Get fetch the cached asset at the given key, and returns true only if the
+// asset was found.
+func (c Cache) Get(key string) (io.Reader, bool) {
+ if c.client != nil {
+ cmd := c.client.Get(key)
+ if b, err := cmd.Bytes(); err == nil {
+ return bytes.NewReader(b), true
+ }
+ }
+ return nil, false
+}
+
+// Set stores an asset to the given key.
+func (c Cache) Set(key string, data []byte, expiration time.Duration) bool {
+ if c.client != nil {
+ c.client.Set(key, data, expiration)
+ }
+ return false
+}
+
+// GetCompressed works like Get but expect a compressed asset that is
+// uncompressed.
+func (c Cache) GetCompressed(key string) (io.Reader, bool) {
+ if r, ok := c.Get(key); ok {
+ if gr, err := gzip.NewReader(r); err == nil {
+ return gr, true
+ }
+ }
+ return nil, false
+}
+
+// SetCompressed works like Set but compress the asset data before storing it.
+func (c Cache) SetCompressed(key string, data []byte, expiration time.Duration) bool {
+ if c.client != nil {
+ dataCompressed := new(bytes.Buffer)
+ gw := gzip.NewWriter(dataCompressed)
+ io.Copy(gw, bytes.NewReader(data))
+ gw.Close()
+ return c.Set(key, dataCompressed.Bytes(), expiration)
+ }
+ return false
+}
diff --git a/pkg/config/config.go b/pkg/config/config.go
index b2d2c5d7cfe..934f749a4dc 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"net"
+ "net/http"
"net/url"
"os"
"path"
@@ -15,6 +16,8 @@ import (
"text/template"
"time"
+ "github.com/cozy/cozy-stack/client/tlsclient"
+ "github.com/cozy/cozy-stack/pkg/cache"
"github.com/cozy/cozy-stack/pkg/keymgmt"
"github.com/cozy/cozy-stack/pkg/logger"
"github.com/cozy/cozy-stack/pkg/utils"
@@ -115,7 +118,6 @@ type Config struct {
Jobs Jobs
Konnectors Konnectors
Mail *gomail.DialerOptions
- AutoUpdates AutoUpdates
Notifications Notifications
Logger logger.Options
@@ -125,11 +127,16 @@ type Config struct {
KonnectorsOauthStateStorage RedisConfig
Realtime RedisConfig
+ CacheStorage cache.Cache
+
Contexts map[string]interface{}
Registries map[string][]*url.URL
CSPDisabled bool
CSPWhitelist map[string]string
+
+ AssetsPollingDisabled bool
+ AssetsPollingInterval time.Duration
}
// Vault contains security keys used for various encryption or signing of
@@ -159,8 +166,9 @@ type Fs struct {
// CouchDB contains the configuration values of the database
type CouchDB struct {
- Auth *url.Userinfo
- URL *url.URL
+ Auth *url.Userinfo
+ URL *url.URL
+ Client *http.Client
}
// Jobs contains the configuration values for the jobs and triggers
@@ -180,12 +188,6 @@ type Konnectors struct {
Cmd string
}
-// AutoUpdates contains the configuration values for auto updates
-type AutoUpdates struct {
- Activated bool
- Schedule string
-}
-
// Notifications contains the configuration for the mobile push-notification
// center, for Android and iOS
type Notifications struct {
@@ -379,6 +381,8 @@ func Setup(cfgFile string) (err error) {
func applyDefaults(v *viper.Viper) {
v.SetDefault("password_reset_interval", defaultPasswordResetInterval)
v.SetDefault("jobs.imagemagick_convert_cmd", "convert")
+ v.SetDefault("assets_polling_disabled", false)
+ v.SetDefault("assets_polling_interval", 2*time.Minute)
}
func envMap() map[string]string {
@@ -416,6 +420,19 @@ func UseViper(v *viper.Viper) error {
if couchURL.Path == "" {
couchURL.Path = "/"
}
+ couchClient, _, err := tlsclient.NewHTTPClient(tlsclient.HTTPEndpoint{
+ Timeout: 10 * time.Second,
+ RootCAFile: v.GetString("couchdb.root_ca"),
+ ClientCertificateFiles: tlsclient.ClientCertificateFilePair{
+ CertificateFile: v.GetString("couchdb.client_cert"),
+ KeyFile: v.GetString("couchdb.client_key"),
+ },
+ PinnedKey: v.GetString("couchdb.pinned_key"),
+ InsecureSkipValidation: v.GetBool("couchdb.insecure_skip_validation"),
+ })
+ if err != nil {
+ return err
+ }
regs, err := makeRegistries(v)
if err != nil {
@@ -491,6 +508,9 @@ func UseViper(v *viper.Viper) error {
return err
}
+ // cache entry is optional
+ cacheRedis, _ := GetRedisConfig(v, redisOptions, "cache", "url")
+
adminSecretFile := v.GetString("admin.secret_filename")
if adminSecretFile == "" {
adminSecretFile = defaultAdminSecretFileName
@@ -582,17 +602,14 @@ func UseViper(v *viper.Viper) error {
URL: fsURL,
},
CouchDB: CouchDB{
- Auth: couchAuth,
- URL: couchURL,
+ Auth: couchAuth,
+ URL: couchURL,
+ Client: couchClient,
},
Jobs: jobs,
Konnectors: Konnectors{
Cmd: v.GetString("konnectors.cmd"),
},
- AutoUpdates: AutoUpdates{
- Activated: v.GetString("auto_updates.schedule") != "",
- Schedule: v.GetString("auto_updates.schedule"),
- },
Notifications: Notifications{
Development: v.GetBool("notifications.development"),
@@ -608,6 +625,7 @@ func UseViper(v *viper.Viper) error {
DownloadStorage: downloadRedis,
KonnectorsOauthStateStorage: konnectorsOauthStateRedis,
Realtime: realtimeRedis,
+ CacheStorage: cache.New(cacheRedis.Client()),
Logger: logger.Options{
Level: v.GetString("log.level"),
Syslog: v.GetBool("log.syslog"),
@@ -625,6 +643,9 @@ func UseViper(v *viper.Viper) error {
Registries: regs,
CSPWhitelist: v.GetStringMapString("csp_whitelist"),
+
+ AssetsPollingDisabled: v.GetBool("assets_polling_disabled"),
+ AssetsPollingInterval: v.GetDuration("assets_polling_interval"),
}
if IsDevRelease() && v.GetBool("disable_csp") {
@@ -730,6 +751,8 @@ func createTestViper() *viper.Viper {
v.SetDefault("fs.url", "mem://test")
v.SetDefault("couchdb.url", "http://localhost:5984/")
v.SetDefault("log.level", "info")
+ v.SetDefault("assets_polling_disabled", false)
+ v.SetDefault("assets_polling_interval", 2*time.Minute)
applyDefaults(v)
return v
}
diff --git a/pkg/config_dyn/assets.go b/pkg/config_dyn/assets.go
new file mode 100644
index 00000000000..b97ef96f122
--- /dev/null
+++ b/pkg/config_dyn/assets.go
@@ -0,0 +1,77 @@
+package config_dyn
+
+import (
+ "time"
+
+ "github.com/cozy/cozy-stack/pkg/consts"
+ "github.com/cozy/cozy-stack/pkg/couchdb"
+ "github.com/cozy/cozy-stack/pkg/statik/fs"
+)
+
+const assetsListID = "assets"
+
+// AssetsList contains the list of assets options that are loaded at the
+// startup of the stack.
+//
+// These assets are either loaded from a persistent cache or loaded directly
+// using their source URL. See statik/fs package for more informations.
+type AssetsList struct {
+ AssetsID string `json:"_id,omitempty"`
+ AssetsRev string `json:"_rev,omitempty"`
+ AssetsList []fs.AssetOption `json:"assets_list"`
+}
+
+func (a *AssetsList) ID() string { return assetsListID }
+func (a *AssetsList) Rev() string { return a.AssetsRev }
+func (a *AssetsList) DocType() string { return consts.Configs }
+
+func (a *AssetsList) Clone() couchdb.Doc {
+ clone := *a
+ clone.AssetsList = make([]fs.AssetOption, len(a.AssetsList))
+ copy(clone.AssetsList, a.AssetsList)
+ return &clone
+}
+
+func (a *AssetsList) SetID(id string) { a.AssetsID = id }
+func (a *AssetsList) SetRev(rev string) { a.AssetsRev = rev }
+
+var _ couchdb.Doc = &AssetsList{}
+
+// GetAssetsList fetches the configuration document containing the list of
+// assets required by the stack.
+func GetAssetsList() ([]fs.AssetOption, error) {
+ var doc AssetsList
+ if err := couchdb.GetDoc(couchdb.GlobalDB, consts.Configs, assetsListID, &doc); err != nil {
+ if !couchdb.IsNoDatabaseError(err) && !couchdb.IsNotFoundError(err) {
+ return nil, err
+ }
+ }
+ return doc.AssetsList, nil
+}
+
+// UpdateAssetsList updates the assets list document in CouchDB to reflect the
+// current list of assets.
+func UpdateAssetsList() error {
+ var doc AssetsList
+ fs.Foreach(func(name, context string, f *fs.Asset) {
+ if f.IsCustom {
+ doc.AssetsList = append(doc.AssetsList, f.AssetOption)
+ }
+ })
+ return couchdb.Upsert(couchdb.GlobalDB, &doc)
+}
+
+// PollAssetsList executes itself in its own goroutine to poll at regular
+// intervals the list of assets that should be delivered by the stack.
+func PollAssetsList(cacheStorage fs.Cache, pollingInterval time.Duration) {
+ if pollingInterval == 0 {
+ pollingInterval = 2 * time.Minute
+ }
+ for {
+ time.Sleep(pollingInterval)
+ assetsList, err := GetAssetsList()
+ if err == nil {
+ fs.RegisterCustomExternals(cacheStorage, assetsList, 6 /*= retry count */)
+ }
+ }
+}
diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go
index 9ed90bc5700..79ef665de07 100644
--- a/pkg/consts/consts.go
+++ b/pkg/consts/consts.go
@@ -3,13 +3,14 @@ package consts
// Instances doc type for User's instance document
const Instances = "instances"
+// Configs doc type assets documents configuration
+const Configs = "configs"
+
const (
// Apps doc type for client-side application manifests
Apps = "io.cozy.apps"
// Konnectors doc type for konnector application manifests
Konnectors = "io.cozy.konnectors"
- // KonnectorResults doc type for konnector last execution result
- KonnectorResults = "io.cozy.konnectors.result"
// Versions doc type for apps versions from the registries
Versions = "io.cozy.registry.versions"
// KonnectorLogs doc type for konnector last execution logs.
diff --git a/pkg/couchdb/couchdb.go b/pkg/couchdb/couchdb.go
index ca8fc54ac49..988d45a355a 100644
--- a/pkg/couchdb/couchdb.go
+++ b/pkg/couchdb/couchdb.go
@@ -232,10 +232,6 @@ func (j JSONDoc) Match(field, value string) bool {
return fmt.Sprintf("%v", j.Get(field)) == value
}
-var couchdbClient = &http.Client{
- Timeout: 10 * time.Second,
-}
-
func unescapeCouchdbName(name string) string {
return strings.Replace(name, "-", ".", -1)
}
@@ -305,7 +301,7 @@ func makeRequest(db Database, doctype, method, path string, reqbody interface{},
}
}
start := time.Now()
- resp, err := couchdbClient.Do(req)
+ resp, err := config.GetConfig().CouchDB.Client.Do(req)
elapsed := time.Since(start)
// Possible err = mostly connection failure
if err != nil {
@@ -769,9 +765,13 @@ func FindDocs(db Database, doctype string, req *FindRequest, results interface{}
return FindDocsRaw(db, doctype, req, results)
}
-// FindDocsRaw find documents
-// TODO: pagination
-func FindDocsRaw(db Database, doctype string, req interface{}, results interface{}) error {
+// FindDocsUnoptimized allows search on non-indexed fields.
+// /!\ Use with care
+func FindDocsUnoptimized(db Database, doctype string, req interface{}, results interface{}) error {
+ return findDocsRaw(db, doctype, req, results, true)
+}
+
+func findDocsRaw(db Database, doctype string, req interface{}, results interface{}, ignoreUnoptimized bool) error {
url := "_find"
// prepare a structure to receive the results
var response findResponse
@@ -788,13 +788,19 @@ func FindDocsRaw(db Database, doctype string, req interface{}, results interface
}
return err
}
- if response.Warning != "" {
+ if !ignoreUnoptimized && response.Warning != "" {
// Developer should not rely on unoptimized index.
return unoptimalError()
}
return json.Unmarshal(response.Docs, results)
}
+// FindDocsRaw find documents
+// TODO: pagination
+func FindDocsRaw(db Database, doctype string, req interface{}, results interface{}) error {
+ return findDocsRaw(db, doctype, req, results, false)
+}
+
// NormalDocs returns all the documents from a database, with pagination, but
// it excludes the design docs.
func NormalDocs(db Database, doctype string, skip, limit int) (*NormalDocsResponse, error) {
diff --git a/pkg/couchdb/proxy.go b/pkg/couchdb/proxy.go
index f0a092ac2e5..6d3d241542f 100644
--- a/pkg/couchdb/proxy.go
+++ b/pkg/couchdb/proxy.go
@@ -34,8 +34,16 @@ func Proxy(db Database, doctype, path string) *httputil.ReverseProxy {
}
}
+ var transport http.RoundTripper
+ if client := config.GetConfig().CouchDB.Client; client != nil {
+ transport = client.Transport
+ } else {
+ transport = http.DefaultTransport
+ }
+
return &httputil.ReverseProxy{
- Director: director,
+ Director: director,
+ Transport: transport,
}
}
@@ -67,9 +75,16 @@ func ProxyBulkDocs(db Database, doctype string, req *http.Request) (*httputil.Re
// reset body to proxy
req.Body = ioutil.NopCloser(bytes.NewReader(body))
+ var transport http.RoundTripper
+ if client := config.GetConfig().CouchDB.Client; client != nil {
+ transport = client.Transport
+ } else {
+ transport = http.DefaultTransport
+ }
+
p := Proxy(db, doctype, "/_bulk_docs")
p.Transport = &bulkTransport{
- RoundTripper: http.DefaultTransport,
+ RoundTripper: transport,
OnResponseRead: func(data []byte) {
type respValue struct {
ID string `json:"id"`
diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go
index 358e4dd1e55..4293f6d1763 100644
--- a/pkg/instance/instance.go
+++ b/pkg/instance/instance.go
@@ -378,7 +378,7 @@ func (i *Instance) SettingsContext() (map[string]interface{}, error) {
}
// Registries returns the list of registries associated with the instance.
-func (i *Instance) Registries() ([]*url.URL, error) {
+func (i *Instance) Registries() []*url.URL {
registries := config.GetConfig().Registries
var regs []*url.URL
var ok bool
@@ -391,7 +391,7 @@ func (i *Instance) Registries() ([]*url.URL, error) {
regs = make([]*url.URL, 0)
}
}
- return regs, nil
+ return regs
}
// DiskQuota returns the number of bytes allowed on the disk to the user.
@@ -536,16 +536,12 @@ func (i *Instance) OnboardedRedirection() *url.URL {
func (i *Instance) installApp(slug string) error {
source := "registry://" + slug + "/stable"
- registries, err := i.Registries()
- if err != nil {
- return err
- }
inst, err := apps.NewInstaller(i, i.AppsCopier(apps.Webapp), &apps.InstallerOptions{
Operation: apps.Install,
Type: apps.Webapp,
SourceURL: source,
Slug: slug,
- Registries: registries,
+ Registries: i.Registries(),
})
if err != nil {
return err
@@ -1008,7 +1004,7 @@ func Patch(i *Instance, opts *Options) error {
if settingsUpdate {
oldSettings, err := i.SettingsDocument()
- if err != nil {
+ if err == nil {
old := oldSettings.M["email"]
new := settings.M["email"]
if old != new {
diff --git a/pkg/instance/manager.go b/pkg/instance/manager.go
index 2825dbba20d..db136610cbb 100644
--- a/pkg/instance/manager.go
+++ b/pkg/instance/manager.go
@@ -60,7 +60,7 @@ func (i *Instance) ManagerURL(k ManagerURLKind) (s string, ok bool) {
// TODO: we may want to rely on the contexts to avoid hardcoding the path
// values of these kinds.
case ManagerPremiumURL:
- path = fmt.Sprintf("/cozy/accounts/%s/premium", url.PathEscape(i.UUID))
+ path = fmt.Sprintf("/cozy/instances/%s/premium", url.PathEscape(i.UUID))
case ManagerTOSURL:
path = fmt.Sprintf("/cozy/instances/%s/tos", url.PathEscape(i.UUID))
case ManagerBlockedURL:
diff --git a/pkg/jobs/cron.go b/pkg/jobs/cron.go
deleted file mode 100644
index 002bc405c17..00000000000
--- a/pkg/jobs/cron.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package jobs
-
-import (
- "context"
- "strings"
- "time"
-
- "github.com/cozy/cozy-stack/pkg/prefixer"
- "github.com/cozy/cozy-stack/pkg/utils"
- "github.com/robfig/cron"
-)
-
-// CronSpec defines a cron process run by the stack, executing a worker with
-// the given cron schedule specification.
-type CronSpec struct {
- Activated bool
- Schedule string
- WorkerType string
- WorkerTemplate func() (Message, error)
-}
-
-type cronner struct {
- spec CronSpec
- schedule cron.Schedule
- sys JobSystem
- stopped chan struct{}
- finished chan struct{}
-}
-
-// CronJobs starts a list of cron specification jobs. It is used to define a
-// serie for recurring jobs that the stack may have to perform as a cron-like
-// daemon.
-func CronJobs(specs []CronSpec) (utils.Shutdowner, error) {
- var s []utils.Shutdowner
- sys := System()
- for _, spec := range specs {
- if !spec.Activated {
- continue
- }
- schedule, err := cron.Parse(strings.TrimPrefix(spec.Schedule, "@cron"))
- if err != nil {
- return nil, err
- }
- s = append(s, cronJob(spec, schedule, sys))
- }
- return utils.NewGroupShutdown(s...), nil
-}
-
-func cronJob(spec CronSpec, schedule cron.Schedule, sys JobSystem) *cronner {
- c := &cronner{
- spec: spec,
- schedule: schedule,
- sys: sys,
- stopped: make(chan struct{}),
- finished: make(chan struct{}),
- }
- go c.run()
- return c
-}
-
-func (c *cronner) run() {
- next := time.Now()
- defer func() {
- c.finished <- struct{}{}
- }()
- for {
- next = c.schedule.Next(next)
- select {
- case <-time.After(-time.Since(next)):
- msg, err := c.spec.WorkerTemplate()
- if err != nil {
- joblog.Errorf("cron: could not generate job template %q: %s",
- c.spec.WorkerType, err)
- continue
- }
- _, err = c.sys.PushJob(prefixer.GlobalPrefixer, &JobRequest{
- WorkerType: c.spec.WorkerType,
- Message: msg,
- })
- if err != nil {
- joblog.Errorf("cron: could not push a new job %q: %s",
- c.spec.WorkerType, err)
- }
- case <-c.stopped:
- return
- }
- }
-}
-
-func (c *cronner) Shutdown(ctx context.Context) error {
- c.stopped <- struct{}{}
- select {
- case <-ctx.Done():
- return ctx.Err()
- case <-c.finished:
- return nil
- }
-}
diff --git a/pkg/jobs/mem_broker.go b/pkg/jobs/mem_broker.go
index a1a0611b54b..994d1676e8b 100644
--- a/pkg/jobs/mem_broker.go
+++ b/pkg/jobs/mem_broker.go
@@ -187,16 +187,22 @@ func (b *memBroker) PushJob(db prefixer.Prefixer, req *JobRequest) (*Job, error)
if worker.Conf.AdminOnly && !req.Admin {
return nil, ErrUnknownWorker
}
+
+ job := NewJob(db, req)
if worker.Conf.BeforeHook != nil {
- if ok, err := worker.Conf.BeforeHook(req); !ok || err != nil {
+ ok, err := worker.Conf.BeforeHook(job)
+ if err != nil {
return nil, err
}
+ if !ok {
+ return job, nil
+ }
}
- job := NewJob(db, req)
if err := job.Create(); err != nil {
return nil, err
}
+
q := b.queues[workerType]
if err := q.Enqueue(job); err != nil {
return nil, err
diff --git a/pkg/jobs/redis_broker.go b/pkg/jobs/redis_broker.go
index eaba72620c2..20f788fa1be 100644
--- a/pkg/jobs/redis_broker.go
+++ b/pkg/jobs/redis_broker.go
@@ -22,11 +22,12 @@ const (
)
type redisBroker struct {
- client redis.UniversalClient
- workers []*Worker
- workersTypes []string
- running uint32
- closed chan struct{}
+ client redis.UniversalClient
+ workers []*Worker
+ workersRunning []*Worker
+ workersTypes []string
+ running uint32
+ closed chan struct{}
}
// NewRedisBroker creates a new broker that will use redis to distribute
@@ -46,24 +47,25 @@ func (b *redisBroker) StartWorkers(ws WorkersList) error {
for _, conf := range ws {
b.workersTypes = append(b.workersTypes, conf.WorkerType)
- ch := make(chan *Job)
w := NewWorker(conf)
b.workers = append(b.workers, w)
if conf.Concurrency <= 0 {
continue
}
+ b.workersRunning = append(b.workersRunning, w)
+ ch := make(chan *Job)
if err := w.Start(ch); err != nil {
return err
}
go b.pollLoop(redisPrefix+conf.WorkerType, ch)
}
- if len(b.workers) > 0 {
- joblog.Infof("Started redis broker for %d workers type", len(b.workers))
+ if len(b.workersRunning) > 0 {
+ joblog.Infof("Started redis broker for %d workers type", len(b.workersRunning))
}
// XXX for retro-compat
- if slots := config.GetConfig().Jobs.NbWorkers; len(b.workers) > 0 && slots > 0 {
+ if slots := config.GetConfig().Jobs.NbWorkers; len(b.workersRunning) > 0 && slots > 0 {
joblog.Warnf("Limiting the number of total concurrent workers to %d", slots)
joblog.Warnf("Please update your configuration file to avoid a hard limit")
setNbSlots(slots)
@@ -80,14 +82,14 @@ func (b *redisBroker) ShutdownWorkers(ctx context.Context) error {
if !atomic.CompareAndSwapUint32(&b.running, 1, 0) {
return ErrClosed
}
- if len(b.workers) == 0 {
+ if len(b.workersRunning) == 0 {
return nil
}
fmt.Print(" shutting down redis broker...")
defer b.client.Close()
- for i := 0; i < len(b.workers); i++ {
+ for i := 0; i < len(b.workersRunning); i++ {
select {
case <-ctx.Done():
fmt.Println("failed:", ctx.Err())
@@ -97,12 +99,12 @@ func (b *redisBroker) ShutdownWorkers(ctx context.Context) error {
}
errs := make(chan error)
- for _, w := range b.workers {
+ for _, w := range b.workersRunning {
go func(w *Worker) { errs <- w.Shutdown(ctx) }(w)
}
var errm error
- for i := 0; i < len(b.workers); i++ {
+ for i := 0; i < len(b.workersRunning); i++ {
if err := <-errs; err != nil {
errm = multierror.Append(errm, err)
}
@@ -191,13 +193,17 @@ func (b *redisBroker) PushJob(db prefixer.Prefixer, req *JobRequest) (*Job, erro
return nil, ErrUnknownWorker
}
+ job := NewJob(db, req)
if worker.Conf.BeforeHook != nil {
- if ok, err := worker.Conf.BeforeHook(req); !ok || err != nil {
+ ok, err := worker.Conf.BeforeHook(job)
+ if err != nil {
return nil, err
}
+ if !ok {
+ return job, nil
+ }
}
- job := NewJob(db, req)
if err := job.Create(); err != nil {
return nil, err
}
diff --git a/pkg/jobs/scheduler.go b/pkg/jobs/scheduler.go
index eaedccd3340..f430a0bbcf3 100644
--- a/pkg/jobs/scheduler.go
+++ b/pkg/jobs/scheduler.go
@@ -187,21 +187,21 @@ func (t *TriggerInfos) Match(key, value string) bool {
}
// GetJobs returns the jobs launched by the given trigger.
-func GetJobs(t Trigger, limit int) ([]*Job, error) {
+func GetJobs(db prefixer.Prefixer, triggerID string, limit int) ([]*Job, error) {
if limit <= 0 || limit > 50 {
limit = 50
}
var jobs []*Job
req := &couchdb.FindRequest{
UseIndex: "by-trigger-id",
- Selector: mango.Equal("trigger_id", t.Infos().ID()),
+ Selector: mango.Equal("trigger_id", triggerID),
Sort: mango.SortBy{
{Field: "trigger_id", Direction: mango.Desc},
{Field: "queued_at", Direction: mango.Desc},
},
Limit: limit,
}
- err := couchdb.FindDocs(t, consts.Jobs, req, &jobs)
+ err := couchdb.FindDocs(db, consts.Jobs, req, &jobs)
if err != nil {
return nil, err
}
@@ -210,8 +210,8 @@ func GetJobs(t Trigger, limit int) ([]*Job, error) {
// GetTriggerState returns the state of the trigger, calculated from the last
// launched jobs.
-func GetTriggerState(t Trigger) (*TriggerState, error) {
- js, err := GetJobs(t, 0)
+func GetTriggerState(db prefixer.Prefixer, triggerID string) (*TriggerState, error) {
+ js, err := GetJobs(db, triggerID, 0)
if err != nil {
return nil, err
}
@@ -219,7 +219,7 @@ func GetTriggerState(t Trigger) (*TriggerState, error) {
var state TriggerState
state.Status = Done
- state.TID = t.ID()
+ state.TID = triggerID
// jobs are ordered from the oldest to most recent job
for i := len(js) - 1; i >= 0; i-- {
diff --git a/pkg/jobs/worker.go b/pkg/jobs/worker.go
index d4f21318931..4ef9052f676 100644
--- a/pkg/jobs/worker.go
+++ b/pkg/jobs/worker.go
@@ -45,7 +45,7 @@ type (
// WorkerBeforeHook is an optional method that is always called before the
// job is being pushed into the queue. It can be useful to skip the job
// beforehand.
- WorkerBeforeHook func(req *JobRequest) (bool, error)
+ WorkerBeforeHook func(job *Job) (bool, error)
// WorkerConfig is the configuration parameter of a worker defined by the job
// system. It contains parameters of the worker along with the worker main
@@ -298,7 +298,7 @@ func (w *Worker) work(workerID string, closed chan<- struct{}) {
// through the global job-system.
if job.TriggerID != "" && globalJobSystem != nil {
if _, ok := errRun.(ErrBadTrigger); ok {
- globalJobSystem.DeleteTrigger(job, job.TriggerID)
+ onBadTriggerError(job)
}
}
}
@@ -306,6 +306,33 @@ func (w *Worker) work(workerID string, closed chan<- struct{}) {
closed <- struct{}{}
}
+// onBadTriggerError is the handler executed when we receive a specific
+// ErrBadTrigger error message:
+// - delete the associated trigger
+// - delete the account document associated with this trigger if any (not activated)
+func onBadTriggerError(job *Job) {
+ // XXX: the account deletion is not activated for now
+ // t, err := globalJobSystem.GetTrigger(job, job.TriggerID)
+ // if err != nil {
+ // return
+ // }
+
+ globalJobSystem.DeleteTrigger(job, job.TriggerID)
+
+ // if job.WorkerType != "konnector" {
+ // return
+ // }
+ // var msg struct {
+ // Account string `json:"account"`
+ // }
+ // if err = t.Infos().Message.Unmarshal(&msg); err == nil && msg.Account != "" {
+ // doc := couchdb.JSONDoc{Type: consts.Accounts}
+ // if err = couchdb.GetDoc(job, consts.Accounts, msg.Account, &doc); err == nil {
+ // couchdb.DeleteDoc(job, &doc)
+ // }
+ // }
+}
+
func (w *Worker) defaultedConf(opts *JobOptions) *WorkerConfig {
c := w.Conf.Clone()
if c.Concurrency == 0 {
diff --git a/pkg/notification/center/notification_center.go b/pkg/notification/center/notification_center.go
index 8c6e25fbe36..aef405c7d52 100644
--- a/pkg/notification/center/notification_center.go
+++ b/pkg/notification/center/notification_center.go
@@ -47,9 +47,13 @@ func init() {
if !ok {
return
}
+ cozyDriveLink := i.SubDomain(consts.DriveSlug)
n := ¬ification.Notification{
State: exceeded,
- Data: map[string]interface{}{"OffersLink": offersLink},
+ Data: map[string]interface{}{
+ "OffersLink": offersLink,
+ "CozyDriveLink": cozyDriveLink.String(),
+ },
}
pushStack(domain, NotificationDiskQuota, n)
})
diff --git a/pkg/oauth/client.go b/pkg/oauth/client.go
index a0f42939052..878346ef411 100644
--- a/pkg/oauth/client.go
+++ b/pkg/oauth/client.go
@@ -157,6 +157,25 @@ func FindClient(i *instance.Instance, id string) (*Client, error) {
return &c, nil
}
+// FindClientBySoftwareID loads a client from the database
+func FindClientBySoftwareID(i *instance.Instance, softwareID string) (*Client, error) {
+ var results []*Client
+
+ req := couchdb.FindRequest{
+ Selector: mango.Equal("software_id", softwareID),
+ Limit: 1,
+ }
+ // We should have very few requests. Only on instance creation.
+ err := couchdb.FindDocsUnoptimized(i, consts.OAuthClients, &req, &results)
+ if err != nil {
+ return nil, err
+ }
+ if len(results) == 1 {
+ return results[0], nil
+ }
+ return nil, fmt.Errorf("Could not find client with software_id %s", softwareID)
+}
+
// ClientRegistrationError is a Client Registration Error Response, as described
// in the Client Dynamic Registration Protocol
// See https://tools.ietf.org/html/rfc7591#section-3.2.2 for errors
diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go
index d1e963e4b01..208bf79da76 100644
--- a/pkg/registry/registry.go
+++ b/pkg/registry/registry.go
@@ -30,13 +30,41 @@ type Version struct {
TarPrefix string `json:"tar_prefix"`
}
-var errVersionNotFound = errors.New("Version not found")
+// A MaintenanceOptions defines options about a maintenance
+type MaintenanceOptions struct {
+ FlagInfraMaintenance bool `json:"flag_infra_maintenance"`
+ FlagShortMaintenance bool `json:"flag_short_maintenance"`
+ FlagDisallowManualExec bool `json:"flag_disallow_manual_exec"`
+}
-var proxyClient = &http.Client{
- Timeout: 10 * time.Second,
- Transport: httpcache.NewMemoryCacheTransport(32),
+// An Application describe an application on the registry
+type Application struct {
+ Slug string `json:"slug"`
+ Type string `json:"type"`
+ MaintenanceActivated bool `json:"maintenance_activated,omitempty"`
+ MaintenanceOptions MaintenanceOptions `json:"maintenance_options"`
}
+var errVersionNotFound = errors.New("registry: version not found")
+var errApplicationNotFound = errors.New("registry: application not found")
+
+var (
+ proxyClient = &http.Client{
+ Timeout: 10 * time.Second,
+ Transport: httpcache.NewMemoryCacheTransport(32),
+ }
+
+ appClient = &http.Client{
+ Timeout: 5 * time.Second,
+ Transport: httpcache.NewMemoryCacheTransport(256),
+ }
+
+ latestVersionClient = &http.Client{
+ Timeout: 5 * time.Second,
+ Transport: httpcache.NewMemoryCacheTransport(256),
+ }
+)
+
// CacheControl defines whether or not to use caching for the request made to
// the registries.
type CacheControl int
@@ -55,7 +83,7 @@ func GetLatestVersion(slug, channel string, registries []*url.URL) (*Version, er
requestURI := fmt.Sprintf("/registry/%s/%s/latest",
url.PathEscape(slug),
url.PathEscape(channel))
- resp, ok, err := fetchUntilFound(registries, requestURI, WithCache)
+ resp, ok, err := fetchUntilFound(latestVersionClient, registries, requestURI, WithCache)
if err != nil {
return nil, err
}
@@ -70,11 +98,29 @@ func GetLatestVersion(slug, channel string, registries []*url.URL) (*Version, er
return v, nil
}
+// GetApplication returns an application from his slug
+func GetApplication(slug string, registries []*url.URL) (*Application, error) {
+ requestURI := fmt.Sprintf("/registry/%s/", slug)
+ resp, ok, err := fetchUntilFound(appClient, registries, requestURI, WithCache)
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ return nil, errApplicationNotFound
+ }
+ defer resp.Body.Close()
+ var app *Application
+ if err = json.NewDecoder(resp.Body).Decode(&app); err != nil {
+ return nil, err
+ }
+ return app, nil
+}
+
// Proxy will proxy the given request to the registries in sequence and return
// the response as io.ReadCloser when finding a registry returning a HTTP 200OK
// response.
func Proxy(req *http.Request, registries []*url.URL, cache CacheControl) (*http.Response, error) {
- resp, ok, err := fetchUntilFound(registries, req.RequestURI, cache)
+ resp, ok, err := fetchUntilFound(proxyClient, registries, req.RequestURI, cache)
if err != nil {
return nil, err
}
@@ -221,7 +267,7 @@ func (a *appsList) fetch(r *registryFetchState, fetchAll bool) error {
"cursor", strconv.Itoa(cursor),
"limit", strconv.Itoa(limit),
)
- resp, ok, err := fetch(r.url, ref, NoCache)
+ resp, ok, err := fetch(proxyClient, r.url, ref, NoCache)
if err != nil {
return err
}
@@ -363,13 +409,13 @@ func (a *appsList) Paginated(sortBy string, reverse bool, limit int) *appsPagina
}
}
-func fetchUntilFound(registries []*url.URL, requestURI string, cache CacheControl) (resp *http.Response, ok bool, err error) {
+func fetchUntilFound(client *http.Client, registries []*url.URL, requestURI string, cache CacheControl) (resp *http.Response, ok bool, err error) {
ref, err := url.Parse(requestURI)
if err != nil {
return
}
for _, registry := range registries {
- resp, ok, err = fetch(registry, ref, cache)
+ resp, ok, err = fetch(client, registry, ref, cache)
if err != nil {
return
}
@@ -381,7 +427,7 @@ func fetchUntilFound(registries []*url.URL, requestURI string, cache CacheContro
return nil, false, nil
}
-func fetch(registry, ref *url.URL, cache CacheControl) (resp *http.Response, ok bool, err error) {
+func fetch(client *http.Client, registry, ref *url.URL, cache CacheControl) (resp *http.Response, ok bool, err error) {
u := registry.ResolveReference(ref)
u.Path = path.Join(registry.Path, ref.Path)
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
@@ -391,7 +437,7 @@ func fetch(registry, ref *url.URL, cache CacheControl) (resp *http.Response, ok
if cache == NoCache {
req.Header.Set("cache-control", "no-cache")
}
- resp, err = proxyClient.Do(req)
+ resp, err = client.Do(req)
if err != nil {
return
}
diff --git a/pkg/sharing/indexer.go b/pkg/sharing/indexer.go
index be4cafc3f0b..be3fcdcf554 100644
--- a/pkg/sharing/indexer.go
+++ b/pkg/sharing/indexer.go
@@ -310,12 +310,12 @@ func (s *sharingIndexer) DirChildExists(dirID, name string) (bool, error) {
return s.indexer.DirChildExists(dirID, name)
}
-func (s *sharingIndexer) BuildTree() (*vfs.TreeFile, error) {
+func (s *sharingIndexer) BuildTree(each ...func(*vfs.TreeFile)) (t *vfs.Tree, err error) {
return nil, ErrInternalServerError
}
-func (s *sharingIndexer) CheckIndexIntegrity() ([]*vfs.FsckLog, error) {
- return nil, ErrInternalServerError
+func (s *sharingIndexer) CheckIndexIntegrity(predicate func(*vfs.FsckLog)) error {
+ return ErrInternalServerError
}
var _ vfs.Indexer = (*sharingIndexer)(nil)
diff --git a/pkg/sharing/sharing.go b/pkg/sharing/sharing.go
index 0ff1b00737a..45430732c9f 100644
--- a/pkg/sharing/sharing.go
+++ b/pkg/sharing/sharing.go
@@ -149,7 +149,8 @@ func (s *Sharing) BeOwner(inst *instance.Instance, slug string) error {
return nil
}
-// CreatePreviewPermissions creates the permissions doc for previewing this sharing
+// CreatePreviewPermissions creates the permissions doc for previewing this sharing,
+// or updates it with the new codes if the document already exists
func (s *Sharing) CreatePreviewPermissions(inst *instance.Instance) (map[string]string, error) {
codes := make(map[string]string, len(s.Members)-1)
for i, m := range s.Members {
@@ -175,9 +176,16 @@ func (s *Sharing) CreatePreviewPermissions(inst *instance.Instance) (map[string]
}
}
- _, err := permissions.CreateSharePreviewSet(inst, s.SID, codes, set)
- if err != nil {
- return nil, err
+ if doc, err := permissions.GetForSharePreview(inst, s.SID); err == nil {
+ doc.Codes = codes
+ if err = couchdb.UpdateDoc(inst, doc); err != nil {
+ return nil, err
+ }
+ } else {
+ _, err := permissions.CreateSharePreviewSet(inst, s.SID, codes, set)
+ if err != nil {
+ return nil, err
+ }
}
return codes, nil
}
diff --git a/pkg/stack/main.go b/pkg/stack/main.go
index 7e213d1ff0b..43bb4afeccc 100644
--- a/pkg/stack/main.go
+++ b/pkg/stack/main.go
@@ -8,6 +8,7 @@ import (
"github.com/cozy/checkup"
"github.com/cozy/cozy-stack/pkg/config"
+ "github.com/cozy/cozy-stack/pkg/config_dyn"
"github.com/cozy/cozy-stack/pkg/consts"
"github.com/cozy/cozy-stack/pkg/fulltext/indexation"
"github.com/cozy/cozy-stack/pkg/fulltext/search"
@@ -15,8 +16,8 @@ import (
"github.com/cozy/cozy-stack/pkg/jobs"
"github.com/cozy/cozy-stack/pkg/logger"
"github.com/cozy/cozy-stack/pkg/sessions"
+ "github.com/cozy/cozy-stack/pkg/statik/fs"
"github.com/cozy/cozy-stack/pkg/utils"
- "github.com/cozy/cozy-stack/pkg/workers/updates"
"github.com/google/gops/agent"
"github.com/sirupsen/logrus"
@@ -61,12 +62,13 @@ security features. Please do not use this binary as your production server.
var db checkup.Result
db, err = checkup.HTTPChecker{
URL: u.String(),
+ Client: config.GetConfig().CouchDB.Client,
MustContain: `"version":"2`,
}.Check()
if err != nil {
err = fmt.Errorf("Could not reach Couchdb 2.0 database: %s", err.Error())
} else if db.Status() == checkup.Down {
- err = fmt.Errorf("Could not reach Couchdb 2.0 database")
+ err = fmt.Errorf("Could not reach Couchdb 2.0 database: %s", db.String())
} else if db.Status() != checkup.Healthy {
log.Warnf("CouchDB does not seem to be in a healthy state, " +
"the cozy-stack will be starting anyway")
@@ -115,30 +117,25 @@ security features. Please do not use this binary as your production server.
return
}
- autoUpdates := config.GetConfig().AutoUpdates
- cronSpecs := []jobs.CronSpec{
- {
- Activated: autoUpdates.Activated,
- Schedule: autoUpdates.Schedule,
- WorkerType: "updates",
- WorkerTemplate: func() (jobs.Message, error) {
- return jobs.NewMessage(updates.Options{AllDomains: true})
- },
- },
- }
-
- // Start update cron for auto-updates
- crons, err := jobs.CronJobs(cronSpecs)
+ assetsList, err := config_dyn.GetAssetsList()
if err != nil {
return
}
+ cacheStorage := config.GetConfig().CacheStorage
+ if err = fs.RegisterCustomExternals(cacheStorage, assetsList, 6 /*= retry count */); err != nil {
+ return
+ }
+ assetsPollingDisabled := config.GetConfig().AssetsPollingDisabled
+ if !assetsPollingDisabled {
+ pollingInterval := config.GetConfig().AssetsPollingInterval
+ go config_dyn.PollAssetsList(cacheStorage, pollingInterval)
+ }
sessionSweeper := sessions.SweepLoginRegistrations()
// Global shutdowner that composes all the running processes of the stack
processes = utils.NewGroupShutdown(
jobs.System(),
- crons,
sessionSweeper,
gopAgent{},
)
diff --git a/pkg/statik/fs/fs.go b/pkg/statik/fs/fs.go
new file mode 100644
index 00000000000..4f44da69f3a
--- /dev/null
+++ b/pkg/statik/fs/fs.go
@@ -0,0 +1,355 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package fs contains an HTTP file system that works with zip contents.
+package fs
+
+import (
+ "bytes"
+ "compress/gzip"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/pem"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/hashicorp/go-multierror"
+
+ "github.com/cozy/cozy-stack/pkg/logger"
+ "github.com/cozy/cozy-stack/pkg/magic"
+)
+
+var assetsClient = &http.Client{
+ Timeout: 30 * time.Second,
+}
+
+var globalAssets sync.Map // {context:path -> *Asset}
+
+const sumLen = 10
+const defaultContext = "default"
+
+type AssetOption struct {
+ Name string `json:"name"`
+ Context string `json:"context"`
+ URL string `json:"url"`
+ Shasum string `json:"shasum"`
+ IsCustom bool `json:"is_custom,omitempty"`
+}
+
+// Asset holds unzipped read-only file contents and file metadata.
+type Asset struct {
+ AssetOption
+ Etag string `json:"etag"`
+ NameWithSum string `json:"name_with_sum"`
+ Mime string `json:"mime"`
+
+ zippedData []byte
+ zippedSize string
+ unzippedData []byte
+ unzippedSize string
+}
+
+func (f *Asset) Size() string {
+ return f.unzippedSize
+}
+func (f *Asset) Reader() *bytes.Reader {
+ return bytes.NewReader(f.unzippedData)
+}
+
+func (f *Asset) GzipSize() string {
+ return f.zippedSize
+}
+func (f *Asset) GzipReader() *bytes.Reader {
+ return bytes.NewReader(f.zippedData)
+}
+
+// Register registers zip contents data, later used to
+// initialize the statik file system.
+func Register(zipData string) {
+ if zipData == "" {
+ panic("statik/fs: no zip data registered")
+ }
+ if err := unzip([]byte(zipData)); err != nil {
+ panic(fmt.Errorf("statik/fs: error unzipping data: %s", err))
+ }
+}
+
+type Cache interface {
+ Get(key string) (io.Reader, bool)
+ Set(key string, data []byte, expiration time.Duration) bool
+}
+
+func RegisterCustomExternals(cache Cache, opts []AssetOption, maxTryCount int) error {
+ if len(opts) == 0 {
+ return nil
+ }
+
+ assetsCh := make(chan AssetOption)
+ doneCh := make(chan []error)
+
+ for i := 0; i < 16; i++ {
+ go func() {
+ var err error
+ var errorsResult []error
+
+ for opt := range assetsCh {
+ sleepDuration := 500 * time.Millisecond
+
+ for tryCount := 0; tryCount < maxTryCount+1; tryCount++ {
+ err = registerCustomExternal(cache, opt)
+ if err == nil {
+ break
+ }
+ if tryCount == maxTryCount {
+ errorsResult = append(errorsResult, err)
+ }
+ logger.WithNamespace("statik").
+ Errorf("Could not load asset from %q, retrying in %s", opt.URL, sleepDuration)
+ time.Sleep(sleepDuration)
+ sleepDuration *= 2
+ }
+ }
+
+ doneCh <- errorsResult
+ }()
+ }
+
+ for _, opt := range opts {
+ assetsCh <- opt
+ }
+ close(assetsCh)
+
+ var errm error
+ for i := 0; i < 16; i++ {
+ if errs := <-doneCh; len(errs) > 0 {
+ errm = multierror.Append(errm, errs...)
+ }
+ }
+ return errm
+}
+
+func registerCustomExternal(cache Cache, opt AssetOption) error {
+ name := normalizeAssetName(opt.Name)
+ if currentAsset, ok := Get(name, opt.Context); ok {
+ if currentAsset.Shasum == opt.Shasum {
+ return nil
+ }
+ }
+
+ opt.IsCustom = true
+
+ assetURL := opt.URL
+ key := fmt.Sprintf("assets:%s:%s:%s", opt.Context, name, opt.Shasum)
+
+ var body io.Reader
+ var ok, storeInCache bool
+ if body, ok = cache.Get(key); !ok {
+ u, err := url.Parse(assetURL)
+ if err != nil {
+ return err
+ }
+
+ switch u.Scheme {
+ case "http", "https":
+ req, err := http.NewRequest(http.MethodGet, assetURL, nil)
+ if err != nil {
+ return err
+ }
+ res, err := assetsClient.Do(req)
+ if err != nil {
+ return err
+ }
+ if res.StatusCode != http.StatusOK {
+ return fmt.Errorf("could not load external asset on %s: status code %d", assetURL, res.StatusCode)
+ }
+ defer res.Body.Close()
+ body = res.Body
+ case "file":
+ f, err := os.Open(u.Path)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ body = f
+ default:
+ return fmt.Errorf("does not support externals assets with scheme %q", u.Scheme)
+ }
+
+ storeInCache = true
+ }
+
+ h := sha256.New()
+
+ zippedDataBuf := new(bytes.Buffer)
+ gw := gzip.NewWriter(zippedDataBuf)
+
+ teeReader := io.TeeReader(body, io.MultiWriter(h, gw))
+ unzippedData, err := ioutil.ReadAll(teeReader)
+ if err != nil {
+ return err
+ }
+ if errc := gw.Close(); errc != nil {
+ return err
+ }
+
+ sum := h.Sum(nil)
+ if hex.EncodeToString(sum) != opt.Shasum {
+ return fmt.Errorf("external content checksum do not match: expected %s got %x on url %s",
+ opt.Shasum, sum, assetURL)
+ }
+
+ if storeInCache {
+ expiration := 30 * 24 * time.Hour
+ cache.Set(key, unzippedData, expiration)
+ }
+
+ asset := newAsset(opt, zippedDataBuf.Bytes(), unzippedData)
+ storeAsset(asset)
+ return nil
+}
+
+func unzip(data []byte) (err error) {
+ for {
+ block, rest := pem.Decode(data)
+ if block == nil {
+ break
+ }
+ var zippedData, unzippedData []byte
+ zippedData = block.Bytes
+ var gr *gzip.Reader
+ gr, err = gzip.NewReader(bytes.NewReader(block.Bytes))
+ if err != nil {
+ return
+ }
+ h := sha256.New()
+ r := io.TeeReader(gr, h)
+ unzippedData, err = ioutil.ReadAll(r)
+ if err != nil {
+ return
+ }
+ if err = gr.Close(); err != nil {
+ return
+ }
+
+ name := block.Headers["Name"]
+ opt := AssetOption{
+ Name: name,
+ Context: defaultContext,
+ Shasum: hex.EncodeToString(h.Sum(nil)),
+ }
+ asset := newAsset(opt, zippedData, unzippedData)
+ storeAsset(asset)
+ data = rest
+ }
+ return
+}
+
+func normalizeAssetName(name string) string {
+ return path.Join("/", name)
+}
+
+func newAsset(opt AssetOption, zippedData, unzippedData []byte) *Asset {
+ mime := magic.MIMETypeByExtension(path.Ext(opt.Name))
+ if mime == "" {
+ mime = magic.MIMEType(unzippedData)
+ }
+ if mime == "" {
+ mime = "application/octet-stream"
+ }
+
+ sumx := opt.Shasum
+ etag := fmt.Sprintf(`"%s"`, sumx[:sumLen])
+
+ opt.Name = normalizeAssetName(opt.Name)
+
+ nameWithSum := opt.Name
+ nameBase := path.Base(opt.Name)
+ if off := strings.IndexByte(nameBase, '.'); off >= 0 {
+ nameDir := path.Dir(opt.Name)
+ nameWithSum = path.Join("/", nameDir, nameBase[:off]+"."+sumx[:sumLen]+nameBase[off:])
+ }
+
+ return &Asset{
+ AssetOption: opt,
+ Etag: etag,
+ NameWithSum: nameWithSum,
+ Mime: mime,
+ zippedData: zippedData,
+ zippedSize: strconv.Itoa(len(zippedData)),
+
+ unzippedData: unzippedData,
+ unzippedSize: strconv.Itoa(len(unzippedData)),
+ }
+}
+
+// threadsafe
+func storeAsset(asset *Asset) {
+ context := asset.Context
+ if context == "" {
+ context = defaultContext
+ }
+ contextKey := marshalContextKey(context, asset.Name)
+ globalAssets.Store(contextKey, asset)
+}
+
+func Get(name string, context ...string) (*Asset, bool) {
+ var ctx string
+ if len(context) > 0 && context[0] != "" {
+ ctx = context[0]
+ } else {
+ ctx = defaultContext
+ }
+ asset, ok := globalAssets.Load(marshalContextKey(ctx, name))
+ if !ok {
+ return nil, false
+ }
+ return asset.(*Asset), true
+}
+
+func Open(name string, context ...string) (*bytes.Reader, error) {
+ f, ok := Get(name, context...)
+ if ok {
+ return f.Reader(), nil
+ }
+ return nil, os.ErrNotExist
+}
+
+func Foreach(predicate func(name, context string, f *Asset)) {
+ globalAssets.Range(func(contextKey interface{}, v interface{}) bool {
+ context, name, _ := unMarshalContextKey(contextKey.(string))
+ predicate(name, context, v.(*Asset))
+ return true
+ })
+}
+
+func marshalContextKey(context, name string) (marshaledKey string) {
+ return context + ":" + name
+}
+
+func unMarshalContextKey(contextKey string) (context string, name string, err error) {
+ unmarshaled := strings.SplitN(contextKey, ":", 2)
+ if len(unmarshaled) != 2 {
+ panic("statik/fs: the contextKey is malformed")
+ }
+ return unmarshaled[0], unmarshaled[1], nil
+}
diff --git a/pkg/statik/statik.go b/pkg/statik/statik.go
new file mode 100644
index 00000000000..6bd4055d313
--- /dev/null
+++ b/pkg/statik/statik.go
@@ -0,0 +1,531 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package contains a program that generates code to register
+// a directory and its contents as zip data for statik file system.
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/pem"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+
+ humanize "github.com/dustin/go-humanize"
+)
+
+const (
+ namePackage = "statik"
+ nameSourceFile = "statik.go"
+)
+
+var (
+ flagSrc = flag.String("src", path.Join(".", "public"), "The path of the source directory.")
+ flagDest = flag.String("dest", ".", "The destination path of the generated package.")
+ flagExternals = flag.String("externals", "", "File containing a description of externals assets to download.")
+ flagForce = flag.Bool("f", false, "Overwrite destination file if it already exists.")
+)
+
+var (
+ errExternalsMalformed = errors.New("assets externals file malformed")
+)
+
+type asset struct {
+ name string
+ size int64
+ url string
+ data []byte
+ sha256 []byte
+}
+
+func main() {
+ flag.Parse()
+
+ destDir := path.Join(*flagDest, namePackage)
+ destFilename := path.Join(destDir, nameSourceFile)
+
+ file, noChange, err := generateSource(destFilename, *flagSrc, *flagExternals)
+ if err != nil {
+ exitWithError(err)
+ }
+
+ if !noChange {
+ err = os.MkdirAll(destDir, 0755)
+ if err != nil {
+ exitWithError(err)
+ }
+
+ src := file.Name()
+
+ hSrc, err := shasum(src)
+ if err != nil {
+ exitWithError(err)
+ }
+ hDest, err := shasum(destFilename)
+ if err != nil {
+ exitWithError(err)
+ }
+
+ if !bytes.Equal(hSrc, hDest) {
+ err = rename(src, destFilename)
+ if err != nil {
+ exitWithError(err)
+ }
+ fmt.Println("asset file updated successfully")
+ } else {
+ fmt.Println("asset file left unchanged")
+ }
+ } else {
+ fmt.Println("asset file left unchanged")
+ }
+}
+
+func shasum(file string) ([]byte, error) {
+ h := sha256.New()
+ f, err := os.Open(file)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ if _, err := io.Copy(h, f); err != nil {
+ return nil, err
+ }
+ return h.Sum(nil), nil
+}
+
+// rename tries to os.Rename, but fall backs to copying from src
+// to dest and unlink the source if os.Rename fails.
+func rename(src, dest string) error {
+ // Try to rename generated source.
+ if err := os.Rename(src, dest); err == nil {
+ return nil
+ }
+ // If the rename failed (might do so due to temporary file residing on a
+ // different device), try to copy byte by byte.
+ rc, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ rc.Close()
+ os.Remove(src) // ignore the error, source is in tmp.
+ }()
+
+ if _, err = os.Stat(dest); !os.IsNotExist(err) {
+ if *flagForce {
+ if err = os.Remove(dest); err != nil {
+ return fmt.Errorf("file %q could not be deleted", dest)
+ }
+ } else {
+ return fmt.Errorf("file %q already exists; use -f to overwrite", dest)
+ }
+ }
+
+ wc, err := os.Create(dest)
+ if err != nil {
+ return err
+ }
+ defer wc.Close()
+
+ if _, err = io.Copy(wc, rc); err != nil {
+ // Delete remains of failed copy attempt.
+ os.Remove(dest)
+ }
+ return err
+}
+
+func loadAsset(name, srcPath string) (*asset, error) {
+ data := new(bytes.Buffer)
+
+ f, err := os.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ h := sha256.New()
+ r := io.TeeReader(f, h)
+ size, err := io.Copy(data, r)
+ if err != nil {
+ return nil, err
+ }
+
+ relPath, err := filepath.Rel(srcPath, name)
+ if err != nil {
+ return nil, err
+ }
+
+ return &asset{
+ name: path.Join("/", filepath.ToSlash(relPath)),
+ size: size,
+ sha256: h.Sum(nil),
+ data: data.Bytes(),
+ }, nil
+}
+
+// Walks on the source path and generates source code
+// that contains source directory's contents as zip contents.
+// Generates source registers generated zip contents data to
+// be read by the statik/fs HTTP file system.
+func generateSource(destFilename, srcPath, externalsFile string) (f *os.File, noChange bool, err error) {
+ var assets []*asset
+
+ currentAssets, err := readCurrentAssets(destFilename)
+ if err != nil {
+ return
+ }
+
+ doneCh := make(chan error)
+ filesCh := make(chan string)
+ assetsCh := make(chan *asset)
+
+ go func() {
+ defer close(filesCh)
+ err = filepath.Walk(srcPath, func(name string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ // Ignore directories and hidden assets.
+ // No entry is needed for directories in a zip file.
+ // Each file is represented with a path, no directory
+ // entities are required to build the hierarchy.
+ if !fi.IsDir() && !strings.HasPrefix(fi.Name(), ".") {
+ filesCh <- name
+ }
+ return nil
+ })
+ if err != nil {
+ doneCh <- err
+ }
+ }()
+
+ for i := 0; i < 16; i++ {
+ go func() {
+ for name := range filesCh {
+ asset, err := loadAsset(name, srcPath)
+ if err != nil {
+ doneCh <- err
+ return
+ }
+ assetsCh <- asset
+ }
+ doneCh <- nil
+ }()
+ }
+
+ go func() {
+ defer close(assetsCh)
+ for i := 0; i < 16; i++ {
+ if err = <-doneCh; err != nil {
+ return
+ }
+ }
+ }()
+
+ for a := range assetsCh {
+ assets = append(assets, a)
+ }
+ if err != nil {
+ return
+ }
+
+ if externalsFile != "" {
+ var exts []*asset
+ exts, err = downloadExternals(externalsFile, currentAssets)
+ if err != nil {
+ return
+ }
+ assets = append(assets, exts...)
+ }
+
+ sort.Slice(assets, func(i, j int) bool {
+ return assets[i].name < assets[j].name
+ })
+
+ if len(assets) == len(currentAssets) {
+ noChange = true
+ for i, a := range assets {
+ old := currentAssets[i]
+ if old.name != a.name || !bytes.Equal(old.sha256, a.sha256) {
+ noChange = false
+ break
+ }
+ }
+ }
+ if noChange {
+ return
+ }
+
+ f, err = ioutil.TempFile("", namePackage)
+ if err != nil {
+ return
+ }
+
+ _, err = fmt.Fprintf(f, `// Code generated by statik. DO NOT EDIT.
+
+package %s
+
+import (
+ "github.com/cozy/cozy-stack/pkg/statik/fs"
+)
+
+func init() {
+ data := `, namePackage)
+ if err != nil {
+ return
+ }
+
+ _, err = fmt.Fprint(f, "`")
+ if err != nil {
+ return
+ }
+
+ err = printZipData(f, assets)
+ if err != nil {
+ return
+ }
+
+ _, err = fmt.Fprint(f, "`")
+ if err != nil {
+ return
+ }
+ _, err = fmt.Fprint(f, `
+ fs.Register(data)
+}
+`)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+func downloadExternals(filename string, currentAssets []*asset) (newAssets []*asset, err error) {
+ externalAssets, err := parseExternalsFile(filename)
+ if err != nil {
+ return
+ }
+
+ currentAssetsMap := make(map[string]*asset)
+ for _, a := range currentAssets {
+ currentAssetsMap[a.name] = a
+ }
+
+ for _, externalAsset := range externalAssets {
+ var newAsset *asset
+ if a, ok := currentAssetsMap[externalAsset.name]; ok && bytes.Equal(a.sha256, externalAsset.sha256) {
+ newAsset = a
+ } else {
+ fmt.Printf("downloading %q... ", externalAsset.name)
+ newAsset, err = downloadExternal(externalAsset)
+ if err != nil {
+ return
+ }
+ fmt.Printf("ok (%s)\n", humanize.Bytes(uint64(newAsset.size)))
+ }
+ newAssets = append(newAssets, newAsset)
+ }
+
+ return
+}
+
+func parseExternalsFile(filename string) (assets []*asset, err error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return
+ }
+ defer func() {
+ if errc := f.Close(); errc != nil && err == nil {
+ err = errc
+ }
+ }()
+
+ var a *asset
+ scanner := bufio.NewScanner(f)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if len(line) > 0 && line[0] == '#' {
+ continue
+ }
+ fields := strings.Fields(line)
+ switch len(fields) {
+ case 0:
+ if a != nil {
+ return nil, errExternalsMalformed
+ }
+ case 2:
+ if a == nil {
+ a = new(asset)
+ }
+ k, v := fields[0], fields[1]
+ switch strings.ToLower(k) {
+ case "name":
+ a.name = path.Join("/", v)
+ case "url":
+ a.url = v
+ case "sha256":
+ a.sha256, err = hex.DecodeString(v)
+ if err != nil {
+ return nil, errExternalsMalformed
+ }
+ }
+ default:
+ return nil, errExternalsMalformed
+ }
+ if a != nil && a.name != "" && a.url != "" && len(a.sha256) > 0 {
+ assets = append(assets, a)
+ a = nil
+ }
+ }
+
+ return
+}
+
+func downloadExternal(ext *asset) (f *asset, err error) {
+ res, err := http.Get(ext.url)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+
+ if res.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("could not fetch external assets %q: received status \"%d %s\"",
+ ext.url, res.StatusCode, res.Status)
+ }
+
+ h := sha256.New()
+ r := io.TeeReader(res.Body, h)
+
+ data, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, fmt.Errorf("could not fetch external asset: %s", err)
+ }
+
+ if sum := h.Sum(nil); !bytes.Equal(sum, ext.sha256) {
+ return nil, fmt.Errorf("shasum does not match: expected %x got %x",
+ ext.sha256, sum)
+ }
+
+ return &asset{
+ data: data,
+ name: ext.name,
+ size: int64(len(data)),
+ sha256: ext.sha256,
+ }, nil
+}
+
+func readCurrentAssets(filename string) (assets []*asset, err error) {
+ statikFile, err := ioutil.ReadFile(filename)
+ if err != nil && !os.IsNotExist(err) {
+ return nil, err
+ }
+
+ var zippedData []byte
+ if len(statikFile) > 0 {
+ i := bytes.Index(statikFile, []byte("`"))
+ if i >= 0 {
+ j := bytes.Index(statikFile[i+1:], []byte("`"))
+ if i >= 0 && j > i {
+ zippedData = statikFile[i+1 : i+j]
+ }
+ }
+ }
+
+ for {
+ block, rest := pem.Decode(zippedData)
+ if block == nil {
+ break
+ }
+ var size int64
+ size, err = strconv.ParseInt(block.Headers["Size"], 10, 64)
+ if err != nil {
+ return
+ }
+ var gr *gzip.Reader
+ gr, err = gzip.NewReader(bytes.NewReader(block.Bytes))
+ if err != nil {
+ return
+ }
+ var data []byte
+ h := sha256.New()
+ r := io.TeeReader(gr, h)
+ data, err = ioutil.ReadAll(r)
+ if err != nil {
+ return
+ }
+ if err = gr.Close(); err != nil {
+ return
+ }
+ name := block.Headers["Name"]
+ assets = append(assets, &asset{
+ name: name,
+ size: size,
+ data: data,
+ sha256: h.Sum(nil),
+ })
+ zippedData = rest
+ }
+ return
+}
+
+// printZipData converts zip binary contents to a string literal.
+func printZipData(dest io.Writer, assets []*asset) error {
+ for _, f := range assets {
+ b := new(bytes.Buffer)
+ gw, err := gzip.NewWriterLevel(b, gzip.BestCompression)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(gw, bytes.NewReader(f.data))
+ if err != nil {
+ return err
+ }
+ err = gw.Close()
+ if err != nil {
+ return err
+ }
+ err = pem.Encode(dest, &pem.Block{
+ Type: "COZY ASSET",
+ Bytes: b.Bytes(),
+ Headers: map[string]string{
+ "Name": f.name,
+ "Size": strconv.FormatInt(f.size, 10),
+ },
+ })
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Prints out the error message and exists with a non-success signal.
+func exitWithError(err error) {
+ fmt.Println(err)
+ os.Exit(1)
+}
diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go
index 0c598d9b729..c1816cae933 100644
--- a/pkg/utils/utils.go
+++ b/pkg/utils/utils.go
@@ -200,3 +200,10 @@ func CloneURL(u *url.URL) *url.URL {
}
return &clone
}
+
+func DurationFuzzing(d time.Duration, variation float64) time.Duration {
+ if variation > 1.0 || variation < 0.0 {
+ panic("DurationRandomized: variation should be between 0.0 and 1.0")
+ }
+ return time.Duration(float64(d) * (1.0 + variation*(2.0*rand.Float64()-1.0)))
+}
diff --git a/pkg/vfs/archive.go b/pkg/vfs/archive.go
index 176bec2a576..81d304fffd5 100644
--- a/pkg/vfs/archive.go
+++ b/pkg/vfs/archive.go
@@ -53,7 +53,7 @@ func ContentDisposition(disposition, filename string) string {
escaped = "download"
}
if filename == escaped {
- return fmt.Sprintf("%s; filename=%s", disposition, escaped)
+ return fmt.Sprintf(`%s; filename="%s"`, disposition, escaped)
}
// RFC5987 §3.2 - syntax of ext value
encoded := url.QueryEscape(filename)
diff --git a/pkg/vfs/couchdb_indexer.go b/pkg/vfs/couchdb_indexer.go
index 60e4fb3083c..ac178283e43 100644
--- a/pkg/vfs/couchdb_indexer.go
+++ b/pkg/vfs/couchdb_indexer.go
@@ -3,6 +3,7 @@ package vfs
import (
"encoding/json"
"errors"
+ "fmt"
"os"
"path"
"strings"
@@ -12,7 +13,6 @@ import (
"github.com/cozy/cozy-stack/pkg/couchdb"
"github.com/cozy/cozy-stack/pkg/couchdb/mango"
"github.com/cozy/cozy-stack/pkg/prefixer"
- multierror "github.com/hashicorp/go-multierror"
)
type couchdbIndexer struct {
@@ -483,247 +483,130 @@ func (c *couchdbIndexer) setTrashedForFilesInsideDir(doc *DirDoc, trashed bool)
return couchdb.BulkUpdateDocs(c.db, consts.Files, files, olddocs)
}
-// TreeFile represent a subset of a file/directory structure that can be used
-// in a tree-like representation of the index.
-type TreeFile struct {
- DirOrFileDoc
- FilesChildren []*TreeFile `json:"children,omitempty"`
- FilesChildrenSize int64 `json:"children_size,omitempty"`
- DirsChildren []*TreeFile `json:"directories,omitempty"`
-
- isDir bool
- hasCycle bool
- visited bool
- errs []*treeError
-}
-
-// Clone is part of the couchdb.Doc interface
-func (t *TreeFile) Clone() couchdb.Doc {
- panic("TreeFile must not be cloned")
-}
-
-var _ couchdb.Doc = &TreeFile{}
-
-type treeError struct {
- file *TreeFile
- path string
-}
-
-func (c *couchdbIndexer) CheckIndexIntegrity() (logs []*FsckLog, err error) {
- root, orphans, err := checkIndexIntegrity(func(cb func(entry *TreeFile)) error {
- return couchdb.ForeachDocs(c.db, consts.Files, func(_ string, data json.RawMessage) error {
- var f TreeFile
- if err = json.Unmarshal(data, &f); err == nil {
- cb(&f)
- }
- return err
- })
- })
+func (c *couchdbIndexer) CheckIndexIntegrity(accumulate func(*FsckLog)) (err error) {
+ tree, err := c.BuildTree()
if err != nil {
return
}
- if root == nil {
- logs = append(logs, &FsckLog{Type: IndexMissingRoot})
- return
+
+ // cleanDirsMap browse the given root tree recursively into its children
+ // directories, removing them from the dirsmap table along the way. In the
+ // end, only trees with cycles should stay in the dirsmap.
+ cleanDirsMap(tree.Root, tree.DirsMap, accumulate)
+ for _, entries := range tree.Orphans {
+ for _, f := range entries {
+ if f.IsDir {
+ cleanDirsMap(f, tree.DirsMap, accumulate)
+ }
+ }
}
- logs, err = getLocalTreeLogs(c, root)
- if err != nil {
- return
+ for _, orphanCycle := range tree.DirsMap {
+ orphanCycle.HasCycle = true
+ tree.Orphans[orphanCycle.DirID] = append(tree.Orphans[orphanCycle.DirID], orphanCycle)
}
- for dirID, orphansTree := range orphans {
- for _, entry := range orphansTree {
- var log *FsckLog
- log, err = getOrphanTreeLog(c, dirID, entry)
- if err != nil {
- return
+ for _, orphansTree := range tree.Orphans {
+ for _, orphan := range orphansTree {
+ if !orphan.IsDir {
+ accumulate(&FsckLog{
+ Type: IndexOrphanTree,
+ IsFile: true,
+ FileDoc: orphan,
+ })
+ } else {
+ accumulate(&FsckLog{
+ Type: IndexOrphanTree,
+ IsFile: false,
+ DirDoc: orphan,
+ })
}
- logs = append(logs, log)
}
}
return
}
-func (c *couchdbIndexer) BuildTree() (root *TreeFile, err error) {
- orphans := make(map[string][]*TreeFile, 32)
- dirsmap := make(map[string]*TreeFile, 256)
+func (c *couchdbIndexer) BuildTree(eaches ...func(*TreeFile)) (t *Tree, err error) {
+ t = &Tree{
+ Root: nil,
+ Orphans: make(map[string][]*TreeFile, 32), // DirID -> *FileDoc
+ DirsMap: make(map[string]*TreeFile, 256), // DocID -> *FileDoc
+ }
+
+ // NOTE: the each method is called with objects in no particular order. The
+ // only enforcement is that either the Fullpath of the objet is informed or
+ // the IsOrphan flag is precised. It may be useful to gather along the way
+ // the files without having to browse the whole tree structure.
+ var each func(*TreeFile)
+ if len(eaches) > 0 {
+ each = eaches[0]
+ } else {
+ each = func(*TreeFile) {}
+ }
err = couchdb.ForeachDocs(c.db, consts.Files, func(_ string, data json.RawMessage) error {
- var f TreeFile
+ var f *TreeFile
if erru := json.Unmarshal(data, &f); erru != nil {
return erru
}
- f.isDir = f.Type == consts.DirType
+ f.IsDir = f.Type == consts.DirType
if f.DocID == consts.RootDirID {
- root = &f
- } else if parent, ok := dirsmap[f.DirID]; ok {
- if f.isDir {
- parent.DirsChildren = append(parent.DirsChildren, &f)
+ t.Root = f
+ each(f)
+ } else if parent, ok := t.DirsMap[f.DirID]; ok {
+ if f.IsDir {
+ parent.DirsChildren = append(parent.DirsChildren, f)
} else {
- parent.FilesChildren = append(parent.FilesChildren, &f)
+ parent.FilesChildren = append(parent.FilesChildren, f)
parent.FilesChildrenSize += f.ByteSize
f.Fullpath = path.Join(parent.Fullpath, f.DocName)
}
+ each(f)
} else {
- orphans[f.DirID] = append(orphans[f.DirID], &f)
+ t.Orphans[f.DirID] = append(t.Orphans[f.DirID], f)
}
- if f.isDir {
- if bucket, ok := orphans[f.DocID]; ok {
+ if f.IsDir {
+ if bucket, ok := t.Orphans[f.DocID]; ok {
for _, child := range bucket {
- if child.isDir {
+ if child.IsDir {
f.DirsChildren = append(f.DirsChildren, child)
} else {
f.FilesChildren = append(f.FilesChildren, child)
f.FilesChildrenSize += child.ByteSize
child.Fullpath = path.Join(f.Fullpath, child.DocName)
}
+ each(child)
}
- delete(orphans, f.DocID)
+ delete(t.Orphans, f.DocID)
}
- dirsmap[f.DocID] = &f
+ t.DirsMap[f.DocID] = f
}
return nil
})
- return
-}
-
-func checkIndexIntegrity(generator func(func(entry *TreeFile)) error) (root *TreeFile, orphans map[string][]*TreeFile, err error) {
- orphans = make(map[string][]*TreeFile, 32)
- dirsmap := make(map[string]*TreeFile, 256)
-
- err = generator(func(f *TreeFile) {
- f.isDir = f.Type == consts.DirType
- if f.DocID == consts.RootDirID {
- root = f
- } else if parent, ok := dirsmap[f.DirID]; ok {
- if f.isDir {
- parent.DirsChildren = append(parent.DirsChildren, f)
- } else {
- parent.FilesChildren = append(parent.FilesChildren, f)
- parent.FilesChildrenSize += f.ByteSize
- }
- } else {
- orphans[f.DirID] = append(orphans[f.DirID], f)
- }
- if f.isDir {
- if bucket, ok := orphans[f.DocID]; ok {
- for _, child := range bucket {
- if child.isDir {
- f.DirsChildren = append(f.DirsChildren, child)
- } else {
- f.FilesChildren = append(f.FilesChildren, child)
- f.FilesChildrenSize += child.ByteSize
- }
- }
- delete(orphans, f.DocID)
- }
- dirsmap[f.DocID] = f
- }
- })
- if err != nil || root == nil {
- return
+ if t.Root == nil {
+ return nil, fmt.Errorf("could not find root file")
}
-
- root.errs = reduceTree(root, dirsmap, nil)
- delete(dirsmap, consts.RootDirID)
-
- for _, entries := range orphans {
- for _, f := range entries {
- if f.isDir {
- f.errs = reduceTree(f, dirsmap, nil)
- delete(dirsmap, f.DocID)
- }
+ for _, bucket := range t.Orphans {
+ for _, child := range bucket {
+ child.IsOrphan = true
+ each(child)
}
}
-
- for _, orphanCycle := range dirsmap {
- orphanCycle.hasCycle = true
- orphans[orphanCycle.DirID] = append(orphans[orphanCycle.DirID], orphanCycle)
- }
-
return
}
-func reduceTree(parent *TreeFile, dirsmap map[string]*TreeFile, errs []*treeError) []*treeError {
+func cleanDirsMap(parent *TreeFile, dirsmap map[string]*TreeFile, accumulate func(*FsckLog)) {
delete(dirsmap, parent.DocID)
for _, child := range parent.DirsChildren {
expected := path.Join(parent.Fullpath, child.DocName)
if expected != child.Fullpath {
- errs = append(errs, &treeError{
- file: child,
- path: expected,
- })
- }
- errs = reduceTree(child, dirsmap, errs)
- }
- return errs
-}
-
-func getLocalTreeLogs(c *couchdbIndexer, root *TreeFile) (logs []*FsckLog, errm error) {
- for _, e := range root.errs {
- if e.path != "" {
- olddoc, err := c.DirByID(e.file.DocID)
- if err != nil {
- errm = multierror.Append(errm, err)
- continue
- }
- newdoc := olddoc.Clone().(*DirDoc)
- newdoc.Fullpath = e.path
- logs = append(logs, &FsckLog{
- Type: IndexBadFullpath,
- OldDirDoc: olddoc,
- DirDoc: newdoc,
- Filename: e.path,
+ accumulate(&FsckLog{
+ Type: IndexBadFullpath,
+ DirDoc: child,
+ ExpectedFullpath: expected,
})
}
+ cleanDirsMap(child, dirsmap, accumulate)
}
- return
-}
-
-func getOrphanTreeLog(c *couchdbIndexer, dirID string, orphan *TreeFile) (log *FsckLog, err error) {
- // TODO: For now, we re-attach the orphan trees at the root of the user's
- // directory. We may use the dirID to infer more precisely where we should
- // re-attach this orphan tree. However we should be careful and check if this
- // directory is actually attached to the root.
- log = &FsckLog{}
- log.Type = IndexOrphanTree
- if !orphan.isDir {
- var olddoc *FileDoc
- olddoc, err = c.FileByID(orphan.DocID)
- if err != nil {
- return
- }
- log.IsFile = true
- log.FileDoc = olddoc
- } else {
- var olddoc *DirDoc
- olddoc, err = c.DirByID(orphan.DocID)
- if err != nil {
- return
- }
- log.DirDoc = olddoc
- log.Filename = olddoc.Fullpath
- if orphan.hasCycle || strings.HasPrefix(olddoc.Fullpath, TrashDirName) {
- log.Deletions = listChildren(orphan, nil)
- return
- }
- }
- return
-}
-
-func listChildren(root *TreeFile, files []couchdb.Doc) []couchdb.Doc {
- if !root.visited {
- files = append(files, root)
- // avoid stackoverflow on cycles
- root.visited = true
- for _, child := range root.DirsChildren {
- files = listChildren(child, files)
- }
- for _, child := range root.FilesChildren {
- files = append(files, child)
- }
- }
- return files
}
diff --git a/pkg/vfs/fsck.go b/pkg/vfs/fsck.go
index b0d07093290..9685c2f38e2 100644
--- a/pkg/vfs/fsck.go
+++ b/pkg/vfs/fsck.go
@@ -1,50 +1,41 @@
package vfs
import (
- "encoding/json"
- "fmt"
- "os"
- "path"
-
"github.com/cozy/cozy-stack/pkg/couchdb"
)
// FsckLogType is the type of a FsckLog
-type FsckLogType int
+type FsckLogType string
const (
// IndexMissingRoot is used when the index does not have a root object
- IndexMissingRoot FsckLogType = iota
+ IndexMissingRoot FsckLogType = "index_missing_root"
// IndexOrphanTree used when a part of the tree is detached from the main
// root of the index.
- IndexOrphanTree
+ IndexOrphanTree FsckLogType = "index_orphan_tree"
// IndexBadFullpath used when a directory does not have the correct path
// field given its position in the index.
- IndexBadFullpath
+ IndexBadFullpath FsckLogType = "index_bad_fullpath"
// FileMissing used when a file data is missing from its index entry.
- FileMissing
+ FileMissing FsckLogType = "file_missing"
// IndexMissing is used when the index entry is missing from a file data.
- IndexMissing
+ IndexMissing FsckLogType = "index_missing"
// TypeMismatch is used when a document type does not match in the index and
// underlying filesystem.
- TypeMismatch
+ TypeMismatch FsckLogType = "type_mismatch"
// ContentMismatch is used when a document content checksum does not match
// with the one in the underlying fs.
- ContentMismatch
+ ContentMismatch FsckLogType = "content_mismatch"
)
// FsckLog is a struct for an inconsistency in the VFS
type FsckLog struct {
- Type FsckLogType
- FileDoc *FileDoc
- OldFileDoc *FileDoc
- DirDoc *DirDoc
- OldDirDoc *DirDoc
- Deletions []couchdb.Doc
- IsFile bool
- Filename string
- PruneAction string
- PruneError error
+ Type FsckLogType `json:"type"`
+ FileDoc *TreeFile `json:"file_doc,omitempty"`
+ DirDoc *TreeFile `json:"dir_doc,omitempty"`
+ IsFile bool `json:"is_file"`
+ ContentMismatch *FsckContentMismatch `json:"content_mismatch,omitempty"`
+ ExpectedFullpath string `json:"expected_fullpath,omitempty"`
}
// String returns a string describing the FsckLog
@@ -72,131 +63,59 @@ func (f *FsckLog) String() string {
case IndexMissing:
return "the document is present on the local filesystem but not in the index"
case ContentMismatch:
- return "then document content does not match the store content checksum"
+ return "the document content does not match the store content checksum"
}
panic("bad FsckLog type")
}
-// MarshalJSON implements the json.Marshaler interface
-func (f *FsckLog) MarshalJSON() ([]byte, error) {
- v := map[string]string{
- "filename": f.Filename,
- "message": f.String(),
- }
- if f.IsFile {
- v["file_id"] = f.FileDoc.ID()
- } else {
- v["file_id"] = f.DirDoc.ID()
- }
- if f.PruneAction != "" {
- v["prune_action"] = f.PruneAction
- if f.PruneError != nil {
- v["prune_error"] = f.PruneError.Error()
- }
+type FsckContentMismatch struct {
+ SizeIndex int64 `json:"size_index"`
+ SizeFile int64 `json:"size_file"`
+ MD5SumIndex []byte `json:"md5sum_index"`
+ MD5SumFile []byte `json:"md5sum_file"`
+}
+
+// Tree is returned by the BuildTree method on the indexes. In containes a
+// pointer to the root element of the tree, a map of directories indexed by
+// their ID, and a map of a potential list of orphan file or directories
+// indexed by their DirID.
+type Tree struct {
+ Root *TreeFile
+ DirsMap map[string]*TreeFile
+ Orphans map[string][]*TreeFile
+}
+
+// TreeFile represent a subset of a file/directory structure that can be used
+// in a tree-like representation of the index.
+type TreeFile struct {
+ DirOrFileDoc
+ FilesChildren []*TreeFile `json:"-"`
+ FilesChildrenSize int64 `json:"-"`
+ DirsChildren []*TreeFile `json:"-"`
+
+ IsDir bool `json:"is_dir"`
+ IsOrphan bool `json:"is_orphan"`
+ HasCycle bool `json:"has_cycle"`
+}
+
+func (t *TreeFile) AsFile() *FileDoc {
+ if t.IsDir {
+ panic("calling AsFile on a directory")
}
- return json.Marshal(v)
+ _, fileDoc := t.DirOrFileDoc.Refine()
+ return fileDoc
}
-// FsckPrune tries to fix the given entry in the VFS
-func FsckPrune(fs VFS, indexer Indexer, entry *FsckLog, dryrun bool) {
- switch entry.Type {
- case IndexMissingRoot:
- entry.PruneAction = "no action: requires manual inspection"
- case IndexOrphanTree:
- if entry.IsFile {
- if entry.FileDoc.Trashed {
- entry.PruneAction = "deleting the entry"
- if !dryrun {
- if err := indexer.DeleteFileDoc(entry.FileDoc); err != nil {
- entry.PruneError = err
- }
- }
- } else {
- entry.PruneAction = "no action: requires manual inspection"
- }
- } else {
- if len(entry.Deletions) > 0 {
- entry.PruneAction = "deleting the orphan directory and its children from the index"
- if !dryrun {
- if err := indexer.BatchDelete(entry.Deletions); err != nil {
- entry.PruneError = err
- }
- }
- } else {
- entry.PruneAction = "no action: requires manual inspection"
- }
- }
- case IndexBadFullpath:
- entry.PruneAction = fmt.Sprintf("updating the path attribute of the directory to: %q",
- entry.Filename)
- if !dryrun {
- if err := indexer.UpdateDirDoc(entry.OldDirDoc, entry.DirDoc); err != nil {
- entry.PruneError = err
- }
- }
- case FileMissing:
- entry.PruneAction = "deleting entry from index"
- if dryrun {
- return
- }
- if entry.IsFile {
- if err := indexer.DeleteFileDoc(entry.FileDoc); err != nil {
- entry.PruneError = err
- }
- } else {
- if err := indexer.DeleteDirDoc(entry.DirDoc); err != nil {
- entry.PruneError = err
- }
- }
- case IndexMissing:
- if !entry.IsFile {
- return
- }
- fileDoc := entry.FileDoc
- var orphan bool
- if fileDoc.DirID == "" {
- orphan = true
- } else {
- parentDir, err := indexer.DirByID(fileDoc.DirID)
- if os.IsNotExist(err) {
- orphan = true
- } else if err != nil {
- entry.PruneError = err
- return
- } else {
- fullpath := path.Join(parentDir.Fullpath, fileDoc.Name())
- if _, err := indexer.FileByPath(fullpath); err != nil {
- entry.PruneError = err
- return
- }
- }
- }
- if orphan {
- entry.PruneAction = "creating index entry in orphan directory"
- } else {
- entry.PruneAction = "creating index entry in-place"
- }
- if dryrun {
- return
- }
- if orphan {
- orphanDir, err := Mkdir(fs, OrphansDirName, nil)
- if err != nil {
- entry.PruneError = err
- return
- }
- fileDoc.DirID = orphanDir.ID()
- }
- if err := indexer.CreateFileDoc(fileDoc); err != nil {
- entry.PruneError = err
- }
- case ContentMismatch:
- if !entry.IsFile {
- return
- }
- entry.PruneAction = "updating the index informations to match the stored data"
- if err := indexer.UpdateFileDoc(entry.OldFileDoc, entry.FileDoc); err != nil {
- entry.PruneError = err
- }
+func (t *TreeFile) AsDir() *DirDoc {
+ if !t.IsDir {
+ panic("calling AsDir on a file")
}
+ return t.DirDoc.Clone().(*DirDoc)
+}
+
+// Clone is part of the couchdb.Doc interface
+func (t *TreeFile) Clone() couchdb.Doc {
+ panic("TreeFile must not be cloned")
}
+
+var _ couchdb.Doc = &TreeFile{}
diff --git a/pkg/vfs/vfs.go b/pkg/vfs/vfs.go
index 3cc057fd3db..0640be56854 100644
--- a/pkg/vfs/vfs.go
+++ b/pkg/vfs/vfs.go
@@ -87,13 +87,7 @@ type Fs interface {
DestroyFile(doc *FileDoc) error
// Fsck return the list of inconsistencies in the VFS
- Fsck(opts FsckOptions) (logbook []*FsckLog, err error)
-}
-
-// FsckOptions contains the options for the filesystem check process.
-type FsckOptions struct {
- Prune bool
- DryRun bool
+ Fsck(func(log *FsckLog)) (err error)
}
// File is a reader, writer, seeker, closer iterface representing an opened
@@ -183,8 +177,8 @@ type Indexer interface {
DirChildExists(dirID, filename string) (bool, error)
BatchDelete([]couchdb.Doc) error
- BuildTree() (*TreeFile, error)
- CheckIndexIntegrity() ([]*FsckLog, error)
+ BuildTree(each ...func(*TreeFile)) (tree *Tree, err error)
+ CheckIndexIntegrity(func(*FsckLog)) error
}
// DiskThresholder it an interface that can be implemeted to known how many space
diff --git a/pkg/vfs/vfs_test.go b/pkg/vfs/vfs_test.go
index aaa7742653e..991e25e6a6e 100644
--- a/pkg/vfs/vfs_test.go
+++ b/pkg/vfs/vfs_test.go
@@ -582,7 +582,7 @@ func TestFileCollision(t *testing.T) {
func TestContentDisposition(t *testing.T) {
foo := vfs.ContentDisposition("inline", "foo.jpg")
- assert.Equal(t, `inline; filename=foo.jpg`, foo)
+ assert.Equal(t, `inline; filename="foo.jpg"`, foo)
space := vfs.ContentDisposition("inline", "foo bar.jpg")
assert.Equal(t, `inline; filename="foobar.jpg"; filename*=UTF-8''foo%20bar.jpg`, space)
accents := vfs.ContentDisposition("inline", "héçà ")
@@ -634,7 +634,7 @@ func TestArchive(t *testing.T) {
res := w.Result()
disposition := res.Header.Get("Content-Disposition")
- assert.Equal(t, `attachment; filename=test.zip`, disposition)
+ assert.Equal(t, `attachment; filename="test.zip"`, disposition)
assert.Equal(t, "application/zip", res.Header.Get("Content-Type"))
b, err := ioutil.ReadAll(res.Body)
diff --git a/pkg/vfs/vfsafero/impl.go b/pkg/vfs/vfsafero/impl.go
index a6e673f48d9..4b210e2d52b 100644
--- a/pkg/vfs/vfsafero/impl.go
+++ b/pkg/vfs/vfsafero/impl.go
@@ -10,9 +10,11 @@ import (
"net/url"
"os"
"path"
- "sort"
+ "path/filepath"
"strings"
+ "sync"
+ "github.com/cozy/cozy-stack/pkg/consts"
"github.com/cozy/cozy-stack/pkg/couchdb"
"github.com/cozy/cozy-stack/pkg/lock"
"github.com/cozy/cozy-stack/pkg/logger"
@@ -23,6 +25,8 @@ import (
"github.com/cozy/afero"
)
+var memfsMap sync.Map
+
// aferoVFS is a struct implementing the vfs.VFS interface associated with
// an afero.Fs filesystem. The indexing of the elements of the filesystem is
// done in couchdb.
@@ -60,7 +64,11 @@ func New(db prefixer.Prefixer, index vfs.Indexer, disk vfs.DiskThresholder, mu l
case "file":
fs = afero.NewBasePathFs(afero.NewOsFs(), pth)
case "mem":
- fs = afero.NewMemMapFs()
+ val, ok := memfsMap.Load(db.DomainName())
+ if !ok {
+ val, _ = memfsMap.LoadOrStore(db.DomainName(), afero.NewMemMapFs())
+ }
+ fs = val.(afero.Fs)
default:
return nil, fmt.Errorf("vfsafero: non supported scheme %s", fsURL.Scheme)
}
@@ -336,212 +344,142 @@ func (afs *aferoVFS) OpenFile(doc *vfs.FileDoc) (vfs.File, error) {
return &aferoFileOpen{f}, nil
}
-func (afs *aferoVFS) Fsck(opts vfs.FsckOptions) (logbook []*vfs.FsckLog, err error) {
- if lockerr := afs.mu.Lock(); lockerr != nil {
- return nil, lockerr
- }
- defer afs.mu.Unlock()
- logbook, err = afs.Indexer.CheckIndexIntegrity()
+func (afs *aferoVFS) Fsck(accumulate func(log *vfs.FsckLog)) (err error) {
+ entries := make(map[string]*vfs.TreeFile, 1024)
+ _, err = afs.BuildTree(func(f *vfs.TreeFile) {
+ if !f.IsOrphan {
+ entries[f.Fullpath] = f
+ }
+ })
if err != nil {
return
}
- if opts.Prune {
- afs.fsckPrune(logbook, opts.DryRun)
- }
- root, err := afs.Indexer.DirByPath("/")
- if err != nil {
- return nil, err
- }
- var newLogs []*vfs.FsckLog
- newLogs, err = afs.fsckWalk(root, newLogs)
- if err != nil {
- return nil, err
- }
- sort.Slice(newLogs, func(i, j int) bool {
- return newLogs[i].Filename < newLogs[j].Filename
- })
- logbook = append(logbook, newLogs...)
- if opts.Prune {
- afs.fsckPrune(newLogs, opts.DryRun)
- }
- return logbook, nil
-}
-func (afs *aferoVFS) fsckWalk(dir *vfs.DirDoc, logbook []*vfs.FsckLog) ([]*vfs.FsckLog, error) {
- entries := make(map[string]struct{})
- iter := afs.Indexer.DirIterator(dir, nil)
- for {
- d, f, err := iter.Next()
- if err == vfs.ErrIteratorDone {
- break
- }
+ err = afero.Walk(afs.fs, "/", func(fullpath string, info os.FileInfo, err error) error {
if err != nil {
- return nil, err
+ return err
+ }
+
+ if fullpath == vfs.WebappsDirName ||
+ fullpath == vfs.KonnectorsDirName ||
+ fullpath == vfs.ThumbsDirName {
+ return filepath.SkipDir
}
- var fullpath string
- if f != nil {
- var stat os.FileInfo
- entries[f.DocName] = struct{}{}
- fullpath = path.Join(dir.Fullpath, f.DocName)
- stat, err = afs.fs.Stat(fullpath)
- if _, ok := err.(*os.PathError); ok {
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.FileMissing,
- IsFile: true,
- FileDoc: f,
- Filename: fullpath,
+
+ f, ok := entries[fullpath]
+ if !ok {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.IndexMissing,
+ IsFile: true,
+ FileDoc: fileInfosToFileDoc(fullpath, info),
+ })
+ } else if f.IsDir != info.IsDir() {
+ if f.IsDir {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.TypeMismatch,
+ IsFile: true,
+ FileDoc: f,
+ DirDoc: fileInfosToDirDoc(fullpath, info),
})
- } else if err != nil {
- return nil, err
- } else if stat.IsDir() {
- var dirDoc *vfs.DirDoc
- dirDoc, err = vfs.NewDirDocWithParent(f.DocName, dir, nil)
- if err != nil {
- return nil, err
- }
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.TypeMismatch,
- IsFile: true,
- DirDoc: dirDoc,
- FileDoc: f,
- Filename: fullpath,
+ } else {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.TypeMismatch,
+ IsFile: false,
+ DirDoc: f,
+ FileDoc: fileInfosToFileDoc(fullpath, info),
})
}
- } else {
- entries[d.DocName] = struct{}{}
- var stat os.FileInfo
- stat, err = afs.fs.Stat(d.Fullpath)
- if _, ok := err.(*os.PathError); ok {
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.FileMissing,
- IsFile: false,
- DirDoc: d,
- Filename: d.Fullpath,
- })
- } else if err != nil {
- return nil, err
- } else if !stat.IsDir() {
- var fileDoc *vfs.FileDoc
- fileDoc, err = fileInfosToFileDoc(dir, d.Fullpath, stat)
- if err != nil {
- return nil, err
- }
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.TypeMismatch,
- IsFile: false,
- FileDoc: fileDoc,
- DirDoc: d,
- Filename: d.Fullpath,
+ } else if !f.IsDir {
+ var fd afero.File
+ fd, err = afs.fs.Open(fullpath)
+ if err != nil {
+ return err
+ }
+ h := md5.New()
+ if _, err = io.Copy(h, fd); err != nil {
+ fd.Close()
+ return err
+ }
+ if err = fd.Close(); err != nil {
+ return err
+ }
+ md5sum := h.Sum(nil)
+ if !bytes.Equal(md5sum, f.MD5Sum) || f.ByteSize != info.Size() {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.ContentMismatch,
+ IsFile: true,
+ FileDoc: f,
+ ContentMismatch: &vfs.FsckContentMismatch{
+ SizeFile: info.Size(),
+ SizeIndex: f.ByteSize,
+ MD5SumFile: md5sum,
+ MD5SumIndex: f.MD5Sum,
+ },
})
- } else {
- if logbook, err = afs.fsckWalk(d, logbook); err != nil {
- return nil, err
- }
}
}
- }
-
- fileinfos, err := afero.ReadDir(afs.fs, dir.Fullpath)
+ delete(entries, fullpath)
+ return nil
+ })
if err != nil {
- return nil, err
+ return
}
- for _, fileinfo := range fileinfos {
- if _, ok := entries[fileinfo.Name()]; !ok {
- filename := path.Join(dir.Fullpath, fileinfo.Name())
- if filename == vfs.WebappsDirName ||
- filename == vfs.KonnectorsDirName ||
- filename == vfs.ThumbsDirName {
- continue
- }
- if fileinfo.Size() == 0 {
- continue
- }
- fileDoc, err := fileInfosToFileDoc(dir, filename, fileinfo)
- if err != nil {
- continue
- }
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.IndexMissing,
- IsFile: true,
- FileDoc: fileDoc,
- Filename: filename,
+ for _, f := range entries {
+ if f.IsDir {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.FileMissing,
+ IsFile: false,
+ DirDoc: f,
+ })
+ } else {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.FileMissing,
+ IsFile: true,
+ FileDoc: f,
})
}
}
- return logbook, nil
+ return
}
-func fileInfosToFileDoc(dir *vfs.DirDoc, fullpath string, fileinfo os.FileInfo) (*vfs.FileDoc, error) {
- trashed := strings.HasPrefix(fullpath, vfs.TrashDirName)
- contentType, md5sum, err := extractContentTypeAndMD5(fullpath)
- if err != nil {
- return nil, err
+func fileInfosToDirDoc(fullpath string, fileinfo os.FileInfo) *vfs.TreeFile {
+ return &vfs.TreeFile{
+ DirOrFileDoc: vfs.DirOrFileDoc{
+ DirDoc: &vfs.DirDoc{
+ Type: consts.DirType,
+ DocName: fileinfo.Name(),
+ DirID: "",
+ CreatedAt: fileinfo.ModTime(),
+ UpdatedAt: fileinfo.ModTime(),
+ Fullpath: fullpath,
+ },
+ },
}
+}
+
+func fileInfosToFileDoc(fullpath string, fileinfo os.FileInfo) *vfs.TreeFile {
+ trashed := strings.HasPrefix(fullpath, vfs.TrashDirName)
+ contentType, md5sum, _ := extractContentTypeAndMD5(fullpath)
mime, class := vfs.ExtractMimeAndClass(contentType)
- return vfs.NewFileDoc(
- fileinfo.Name(),
- dir.DocID,
- fileinfo.Size(),
- md5sum,
- mime,
- class,
- fileinfo.ModTime(),
- false,
- trashed,
- nil)
-}
-
-// fsckPrune tries to fix the given list on inconsistencies in the VFS
-func (afs *aferoVFS) fsckPrune(logbook []*vfs.FsckLog, dryrun bool) {
- for _, entry := range logbook {
- switch entry.Type {
- case vfs.IndexOrphanTree, vfs.IndexBadFullpath, vfs.FileMissing, vfs.IndexMissing:
- vfs.FsckPrune(afs, afs.Indexer, entry, dryrun)
- case vfs.TypeMismatch:
- if entry.IsFile {
- // file on couchdb and directory on swift: we update the index to
- // remove the file index and create a directory one
- err := afs.Indexer.DeleteFileDoc(entry.FileDoc)
- if err != nil {
- entry.PruneError = err
- }
- err = afs.Indexer.CreateDirDoc(entry.DirDoc)
- if err != nil {
- entry.PruneError = err
- }
- } else {
- // directory on couchdb and file on filesystem: we keep the directory
- // and move the object into the orphan directory and create a new index
- // associated with it.
- orphanDir, err := vfs.Mkdir(afs, vfs.OrphansDirName, nil)
- if err != nil {
- entry.PruneError = err
- continue
- }
- oldname := entry.Filename
- newname := path.Join(vfs.OrphansDirName, entry.FileDoc.Name())
- err = afs.fs.Rename(oldname, newname)
- if err != nil {
- entry.PruneError = err
- continue
- }
- err = afs.fs.Mkdir(oldname, 0755)
- if err != nil {
- entry.PruneError = err
- continue
- }
- newdoc := entry.FileDoc.Clone().(*vfs.FileDoc)
- newdoc.DirID = orphanDir.ID()
- newdoc.ResetFullpath()
- err = afs.Indexer.CreateFileDoc(newdoc)
- if err != nil {
- entry.PruneError = err
- continue
- }
- }
- }
+ return &vfs.TreeFile{
+ DirOrFileDoc: vfs.DirOrFileDoc{
+ DirDoc: &vfs.DirDoc{
+ Type: consts.FileType,
+ DocName: fileinfo.Name(),
+ DirID: "",
+ CreatedAt: fileinfo.ModTime(),
+ UpdatedAt: fileinfo.ModTime(),
+ Fullpath: fullpath,
+ },
+ ByteSize: fileinfo.Size(),
+ Mime: mime,
+ Class: class,
+ Executable: int(fileinfo.Mode()|0111) > 0,
+ MD5Sum: md5sum,
+ Trashed: trashed,
+ },
}
}
diff --git a/pkg/vfs/vfsswift/impl_v1.go b/pkg/vfs/vfsswift/impl_v1.go
index 4e7894df68d..09a853c08ae 100644
--- a/pkg/vfs/vfsswift/impl_v1.go
+++ b/pkg/vfs/vfsswift/impl_v1.go
@@ -7,10 +7,10 @@ import (
"io/ioutil"
"os"
"path"
- "sort"
"strings"
"github.com/cozy/cozy-stack/pkg/config"
+ "github.com/cozy/cozy-stack/pkg/consts"
"github.com/cozy/cozy-stack/pkg/couchdb"
"github.com/cozy/cozy-stack/pkg/lock"
"github.com/cozy/cozy-stack/pkg/logger"
@@ -80,6 +80,15 @@ func (sfs *swiftVFS) UseSharingIndexer(index vfs.Indexer) vfs.VFS {
}
}
+func (sfs *swiftVFS) ContainersNames() map[string]string {
+ m := map[string]string{
+ "container": sfs.container,
+ "version": sfs.version,
+ "data_container": sfs.dataContainer,
+ }
+ return m
+}
+
func (sfs *swiftVFS) InitFs() error {
if lockerr := sfs.mu.Lock(); lockerr != nil {
return lockerr
@@ -417,223 +426,110 @@ func (sfs *swiftVFS) OpenFile(doc *vfs.FileDoc) (vfs.File, error) {
return &swiftFileOpen{f, nil}, nil
}
-func (sfs *swiftVFS) Fsck(opts vfs.FsckOptions) (logbook []*vfs.FsckLog, err error) {
- if lockerr := sfs.mu.RLock(); lockerr != nil {
- return nil, lockerr
- }
- defer sfs.mu.RUnlock()
- logbook, err = sfs.Indexer.CheckIndexIntegrity()
- if err != nil {
- return
- }
- if opts.Prune {
- sfs.fsckPrune(logbook, opts.DryRun)
- }
- root, err := sfs.Indexer.DirByPath("/")
- if err != nil {
- return
- }
- var newLogs []*vfs.FsckLog
- newLogs, err = sfs.fsckWalk(root, newLogs)
+func (sfs *swiftVFS) Fsck(accumulate func(log *vfs.FsckLog)) (err error) {
+ entries := make(map[string]*vfs.TreeFile, 1024)
+ _, err = sfs.BuildTree(func(f *vfs.TreeFile) {
+ if !f.IsDir {
+ entries[f.DirID+"/"+f.DocName] = f
+ }
+ })
if err != nil {
return
}
- sort.Slice(newLogs, func(i, j int) bool {
- return newLogs[i].Filename < newLogs[j].Filename
- })
- logbook = append(logbook, newLogs...)
- if opts.Prune {
- sfs.fsckPrune(newLogs, opts.DryRun)
- }
- return
-}
-func (sfs *swiftVFS) fsckWalk(dir *vfs.DirDoc, logbook []*vfs.FsckLog) ([]*vfs.FsckLog, error) {
- entries := make(map[string]struct{})
- iter := sfs.Indexer.DirIterator(dir, nil)
- for {
- d, f, err := iter.Next()
- if err == vfs.ErrIteratorDone {
- break
- }
+ var orphansObjs []swift.Object
+
+ err = sfs.c.ObjectsWalk(sfs.container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
+ var objs []swift.Object
+ objs, err = sfs.c.Objects(sfs.container, opts)
if err != nil {
return nil, err
}
-
- if f != nil {
- var info swift.Object
- fullpath := path.Join(dir.Fullpath, f.DocName)
- entries[f.DocName] = struct{}{}
- info, _, err = sfs.c.Object(sfs.container, f.DirID+"/"+f.DocName)
- if err == swift.ObjectNotFound {
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.FileMissing,
- IsFile: true,
- FileDoc: f,
- Filename: fullpath,
- })
- } else if err != nil {
- return nil, err
- } else if info.ContentType == dirContentType {
- var dirDoc *vfs.DirDoc
- name := path.Base(info.Name)
- dirDoc, err = vfs.NewDirDocWithParent(name, dir, nil)
+ for _, obj := range objs {
+ f, ok := entries[obj.Name]
+ if !ok {
+ orphansObjs = append(orphansObjs, obj)
+ } else {
+ var md5sum []byte
+ md5sum, err = hex.DecodeString(obj.Hash)
if err != nil {
return nil, err
}
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.TypeMismatch,
- IsFile: true,
- DirDoc: dirDoc,
- FileDoc: f,
- Filename: fullpath,
- })
- }
- } else {
- entries[d.DocName] = struct{}{}
- if d.Fullpath == vfs.TrashDirName {
- continue
- }
- var info swift.Object
- info, _, err = sfs.c.Object(sfs.container, d.DirID+"/"+d.DocName)
- if err == swift.ObjectNotFound {
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.FileMissing,
- IsFile: false,
- DirDoc: d,
- Filename: d.Fullpath,
- })
- } else if err != nil {
- return nil, err
- } else if info.ContentType != dirContentType {
- var fileDoc *vfs.FileDoc
- _, fileDoc, err = objectToFileDocV1(dir, info)
- if err != nil {
- continue
- }
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.TypeMismatch,
- IsFile: false,
- DirDoc: d,
- FileDoc: fileDoc,
- Filename: d.Fullpath,
- })
- } else {
- if logbook, err = sfs.fsckWalk(d, logbook); err != nil {
- return nil, err
+ if !bytes.Equal(md5sum, f.MD5Sum) || f.ByteSize != obj.Bytes {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.ContentMismatch,
+ IsFile: true,
+ FileDoc: f,
+ ContentMismatch: &vfs.FsckContentMismatch{
+ SizeFile: obj.Bytes,
+ SizeIndex: f.ByteSize,
+ MD5SumFile: md5sum,
+ MD5SumIndex: f.MD5Sum,
+ },
+ })
}
+ delete(entries, obj.Name)
}
}
- }
-
- objects, err := sfs.c.ObjectsAll(sfs.container, &swift.ObjectsOpts{
- Path: dir.DocID,
+ return objs, err
})
- if err != nil {
- return nil, err
+
+ for _, f := range entries {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.FileMissing,
+ IsFile: true,
+ FileDoc: f,
+ })
}
- for _, object := range objects {
- name := path.Base(object.Name)
- if _, ok := entries[name]; !ok {
- if object.Bytes == 0 {
- continue
- }
- filePath, fileDoc, err := objectToFileDocV1(dir, object)
- if err != nil {
- continue
- }
- logbook = append(logbook, &vfs.FsckLog{
- Type: vfs.IndexMissing,
- IsFile: true,
- FileDoc: fileDoc,
- Filename: filePath,
+
+ for _, obj := range orphansObjs {
+ if obj.ContentType == dirContentType {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.IndexMissing,
+ IsFile: false,
+ FileDoc: objectToFileDocV1(sfs.container, obj),
+ })
+ } else {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.IndexMissing,
+ IsFile: true,
+ FileDoc: objectToFileDocV1(sfs.container, obj),
})
}
}
- return logbook, nil
+ return
}
-func objectToFileDocV1(dir *vfs.DirDoc, object swift.Object) (filePath string, fileDoc *vfs.FileDoc, err error) {
- trashed := strings.HasPrefix(dir.Fullpath, vfs.TrashDirName)
- dirID := dir.DocID
- filePath = path.Join(dir.Fullpath, path.Base(object.Name))
- md5sum, err := hex.DecodeString(object.Hash)
- if err != nil {
- return
+func objectToFileDocV1(container string, object swift.Object) *vfs.TreeFile {
+ var dirID, name string
+ if dirIDAndName := strings.SplitN(object.Name, "/", 2); len(dirIDAndName) == 2 {
+ dirID = dirIDAndName[0]
+ name = dirIDAndName[0]
+ }
+ docType := consts.FileType
+ if object.ContentType == dirContentType {
+ docType = consts.DirType
}
+ md5sum, _ := hex.DecodeString(object.Hash)
mime, class := vfs.ExtractMimeAndClass(object.ContentType)
- fileDoc, err = vfs.NewFileDoc(
- path.Base(object.Name),
- dirID,
- object.Bytes,
- md5sum,
- mime,
- class,
- object.LastModified,
- false,
- trashed,
- nil)
- return
-}
-
-// fsckPrune tries to fix the given list on inconsistencies in the VFS
-func (sfs *swiftVFS) fsckPrune(logbook []*vfs.FsckLog, dryrun bool) {
- for _, entry := range logbook {
- switch entry.Type {
- case vfs.IndexOrphanTree, vfs.IndexBadFullpath, vfs.FileMissing, vfs.IndexMissing:
- vfs.FsckPrune(sfs, sfs.Indexer, entry, dryrun)
- case vfs.TypeMismatch:
- if entry.IsFile {
- // file on couchdb and directory on swift: we update the index to
- // remove the file index and create a directory one
- err := sfs.Indexer.DeleteFileDoc(entry.FileDoc)
- if err != nil {
- entry.PruneError = err
- }
- err = sfs.Indexer.CreateDirDoc(entry.DirDoc)
- if err != nil {
- entry.PruneError = err
- }
- } else {
- // directory on couchdb and file on swift: we keep the directory and
- // move the object into the orphan directory and create a new index
- // associated with it.
- orphanDir, err := vfs.Mkdir(sfs, vfs.OrphansDirName, nil)
- if err != nil {
- entry.PruneError = err
- continue
- }
- olddoc := entry.FileDoc
- newdoc := entry.FileDoc.Clone().(*vfs.FileDoc)
- newdoc.DirID = orphanDir.DirID
- newdoc.ResetFullpath()
- err = sfs.c.ObjectMove(
- sfs.container, olddoc.DirID+"/"+olddoc.DocName,
- sfs.container, newdoc.DirID+"/"+newdoc.DocName,
- )
- if err != nil {
- entry.PruneError = err
- continue
- }
- _, err = sfs.c.ObjectCreate(sfs.container,
- olddoc.DirID+"/"+olddoc.DocName,
- true,
- "",
- dirContentType,
- nil,
- )
- if err != nil {
- entry.PruneError = err
- continue
- }
- err = sfs.Indexer.CreateFileDoc(newdoc)
- if err != nil {
- entry.PruneError = err
- continue
- }
- }
- }
+ return &vfs.TreeFile{
+ DirOrFileDoc: vfs.DirOrFileDoc{
+ DirDoc: &vfs.DirDoc{
+ Type: docType,
+ DocID: makeDocID(object.Name),
+ DocName: name,
+ DirID: dirID,
+ CreatedAt: object.LastModified,
+ UpdatedAt: object.LastModified,
+ Fullpath: path.Join(vfs.OrphansDirName, name),
+ },
+ ByteSize: object.Bytes,
+ Mime: mime,
+ Class: class,
+ Executable: false,
+ MD5Sum: md5sum,
+ },
}
}
diff --git a/pkg/vfs/vfsswift/impl_v2.go b/pkg/vfs/vfsswift/impl_v2.go
index f0785437f0c..9c054944019 100644
--- a/pkg/vfs/vfsswift/impl_v2.go
+++ b/pkg/vfs/vfsswift/impl_v2.go
@@ -3,12 +3,10 @@ package vfsswift
import (
"bytes"
"encoding/hex"
- "fmt"
"io"
"io/ioutil"
"os"
"path"
- "sort"
"strconv"
"strings"
"time"
@@ -19,7 +17,6 @@ import (
"github.com/cozy/cozy-stack/pkg/lock"
"github.com/cozy/cozy-stack/pkg/logger"
"github.com/cozy/cozy-stack/pkg/prefixer"
- "github.com/cozy/cozy-stack/pkg/utils"
"github.com/cozy/cozy-stack/pkg/vfs"
"github.com/cozy/swift"
multierror "github.com/hashicorp/go-multierror"
@@ -105,6 +102,15 @@ func (sfs *swiftVFSV2) UseSharingIndexer(index vfs.Indexer) vfs.VFS {
}
}
+func (sfs *swiftVFSV2) ContainersNames() map[string]string {
+ m := map[string]string{
+ "container": sfs.container,
+ "version": sfs.version,
+ "data_container": sfs.dataContainer,
+ }
+ return m
+}
+
func (sfs *swiftVFSV2) InitFs() error {
if lockerr := sfs.mu.Lock(); lockerr != nil {
return lockerr
@@ -399,35 +405,13 @@ func (sfs *swiftVFSV2) OpenFile(doc *vfs.FileDoc) (vfs.File, error) {
return &swiftFileOpenV2{f, nil}, nil
}
-type fsckFile struct {
- file *vfs.FileDoc
- fullpath string
-}
-
-func (sfs *swiftVFSV2) Fsck(opts vfs.FsckOptions) (logbook []*vfs.FsckLog, err error) {
- if lockerr := sfs.mu.RLock(); lockerr != nil {
- return nil, lockerr
- }
- defer sfs.mu.RUnlock()
-
- logbook, err = sfs.Indexer.CheckIndexIntegrity()
- if err != nil {
- return
- }
-
- if opts.Prune {
- sfs.fsckPrune(logbook, opts.DryRun)
- }
-
- var newLogs []*vfs.FsckLog
-
- root, err := sfs.Indexer.DirByID(consts.RootDirID)
- if err != nil {
- return
- }
-
- entries := make(map[string]fsckFile, 256)
- err = sfs.fsckWalk(root, entries)
+func (sfs *swiftVFSV2) Fsck(accumulate func(log *vfs.FsckLog)) (err error) {
+ entries := make(map[string]*vfs.TreeFile, 1024)
+ _, err = sfs.BuildTree(func(f *vfs.TreeFile) {
+ if !f.IsDir {
+ entries[f.DocID] = f
+ }
+ })
if err != nil {
return
}
@@ -442,17 +426,10 @@ func (sfs *swiftVFSV2) Fsck(opts vfs.FsckOptions) (logbook []*vfs.FsckLog, err e
docID := makeDocID(obj.Name)
f, ok := entries[docID]
if !ok {
- var fileDoc *vfs.FileDoc
- var filePath string
- filePath, fileDoc, err = objectToFileDocV2(sfs.c, sfs.container, obj)
- if err != nil {
- return nil, err
- }
- newLogs = append(newLogs, &vfs.FsckLog{
- Type: vfs.IndexMissing,
- IsFile: true,
- FileDoc: fileDoc,
- Filename: filePath,
+ accumulate(&vfs.FsckLog{
+ Type: vfs.IndexMissing,
+ IsFile: true,
+ FileDoc: objectToFileDocV2(sfs.container, obj),
})
} else {
var md5sum []byte
@@ -460,16 +437,17 @@ func (sfs *swiftVFSV2) Fsck(opts vfs.FsckOptions) (logbook []*vfs.FsckLog, err e
if err != nil {
return nil, err
}
- if !bytes.Equal(md5sum, f.file.MD5Sum) {
- olddoc := f.file
- newdoc := olddoc.Clone().(*vfs.FileDoc)
- newdoc.MD5Sum = md5sum
- newLogs = append(newLogs, &vfs.FsckLog{
- Type: vfs.ContentMismatch,
- IsFile: true,
- FileDoc: newdoc,
- OldFileDoc: olddoc,
- Filename: f.fullpath,
+ if !bytes.Equal(md5sum, f.MD5Sum) || f.ByteSize != obj.Bytes {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.ContentMismatch,
+ IsFile: true,
+ FileDoc: f,
+ ContentMismatch: &vfs.FsckContentMismatch{
+ SizeFile: obj.Bytes,
+ SizeIndex: f.ByteSize,
+ MD5SumFile: md5sum,
+ MD5SumIndex: f.MD5Sum,
+ },
})
}
delete(entries, docID)
@@ -483,59 +461,17 @@ func (sfs *swiftVFSV2) Fsck(opts vfs.FsckOptions) (logbook []*vfs.FsckLog, err e
// entries should contain only data that does not contain an associated
// index.
- for docID, f := range entries {
- _, _, err = sfs.c.Object(sfs.container, docID)
- if err == swift.ObjectNotFound {
- newLogs = append(newLogs, &vfs.FsckLog{
- Type: vfs.FileMissing,
- IsFile: true,
- FileDoc: f.file,
- Filename: f.fullpath,
- })
- } else if err != nil {
- return nil, err
- }
- }
- sort.Slice(newLogs, func(i, j int) bool {
- return newLogs[i].Filename < newLogs[j].Filename
- })
-
- logbook = append(logbook, newLogs...)
-
- if opts.Prune {
- sfs.fsckPrune(newLogs, opts.DryRun)
+ for _, f := range entries {
+ accumulate(&vfs.FsckLog{
+ Type: vfs.FileMissing,
+ IsFile: true,
+ FileDoc: f,
+ })
}
return
}
-func (sfs *swiftVFSV2) fsckWalk(dir *vfs.DirDoc, entries map[string]fsckFile) error {
- iter := sfs.Indexer.DirIterator(dir, nil)
- for {
- d, f, err := iter.Next()
- if err == vfs.ErrIteratorDone {
- break
- }
- if err != nil {
- return err
- }
- if f != nil {
- fullpath := path.Join(dir.Fullpath, f.DocName)
- entries[f.DocID] = fsckFile{f, fullpath}
- } else if err = sfs.fsckWalk(d, entries); err != nil {
- return err
- }
- }
- return nil
-}
-
-// fsckPrune tries to fix the given list on inconsistencies in the VFS
-func (sfs *swiftVFSV2) fsckPrune(logbook []*vfs.FsckLog, dryrun bool) {
- for _, entry := range logbook {
- vfs.FsckPrune(sfs, sfs.Indexer, entry, dryrun)
- }
-}
-
// UpdateFileDoc calls the indexer UpdateFileDoc function and adds a few checks
// before actually calling this method:
// - locks the filesystem for writing
@@ -834,43 +770,28 @@ func (f *swiftFileOpenV2) Close() error {
return f.f.Close()
}
-func objectToFileDocV2(c *swift.Connection, container string, object swift.Object) (filePath string, fileDoc *vfs.FileDoc, err error) {
- var h swift.Headers
- _, h, err = c.Object(container, object.Name)
- if err != nil {
- return
- }
- md5sum, err := hex.DecodeString(object.Hash)
- if err != nil {
- return
- }
- objMeta := h.ObjectMetadata()
- name := objMeta["creation-name"]
- if name == "" {
- name = fmt.Sprintf("Unknown %s", utils.RandomString(10))
- }
- var cdate time.Time
- if v := objMeta["created-at"]; v != "" {
- cdate, _ = time.Parse(time.RFC3339, v)
- }
- if cdate.IsZero() {
- cdate = time.Now()
- }
- executable, _ := strconv.ParseBool(objMeta["exec"])
+func objectToFileDocV2(container string, object swift.Object) *vfs.TreeFile {
+ md5sum, _ := hex.DecodeString(object.Hash)
+ name := "unknown"
mime, class := vfs.ExtractMimeAndClass(object.ContentType)
- filePath = path.Join(vfs.OrphansDirName, name)
- fileDoc, err = vfs.NewFileDoc(
- name,
- "",
- object.Bytes,
- md5sum,
- mime,
- class,
- cdate,
- executable,
- false,
- nil)
- return
+ return &vfs.TreeFile{
+ DirOrFileDoc: vfs.DirOrFileDoc{
+ DirDoc: &vfs.DirDoc{
+ Type: consts.FileType,
+ DocID: makeDocID(object.Name),
+ DocName: name,
+ DirID: "",
+ CreatedAt: object.LastModified,
+ UpdatedAt: object.LastModified,
+ Fullpath: path.Join(vfs.OrphansDirName, name),
+ },
+ ByteSize: object.Bytes,
+ Mime: mime,
+ Class: class,
+ Executable: false,
+ MD5Sum: md5sum,
+ },
+ }
}
var (
diff --git a/pkg/workers/exec/common.go b/pkg/workers/exec/common.go
index a01ab114440..e94a2080ea3 100644
--- a/pkg/workers/exec/common.go
+++ b/pkg/workers/exec/common.go
@@ -127,7 +127,7 @@ func worker(ctx *jobs.WorkerContext) (err error) {
}
}
if errs := scanOut.Err(); errs != nil {
- log.Errorf("could not scan stdout: %s", err)
+ log.Errorf("could not scan stdout: %s", errs)
}
}()
diff --git a/pkg/workers/exec/konnector.go b/pkg/workers/exec/konnector.go
index eba358cfabd..d2581a661f5 100644
--- a/pkg/workers/exec/konnector.go
+++ b/pkg/workers/exec/konnector.go
@@ -10,7 +10,6 @@ import (
"path"
"strconv"
"strings"
- "time"
"github.com/cozy/cozy-stack/pkg/accounts"
"github.com/cozy/cozy-stack/pkg/apps"
@@ -19,7 +18,9 @@ import (
"github.com/cozy/cozy-stack/pkg/couchdb"
"github.com/cozy/cozy-stack/pkg/instance"
"github.com/cozy/cozy-stack/pkg/jobs"
+ "github.com/cozy/cozy-stack/pkg/permissions"
"github.com/cozy/cozy-stack/pkg/realtime"
+ "github.com/cozy/cozy-stack/pkg/registry"
"github.com/cozy/cozy-stack/pkg/vfs"
"github.com/sirupsen/logrus"
@@ -33,7 +34,7 @@ const (
type konnectorWorker struct {
slug string
- msg *konnectorMessage
+ msg *KonnectorMessage
man *apps.KonnManifest
err error
@@ -48,43 +49,57 @@ const (
konnectorMsgTypeCritical = "critical"
)
-type konnectorMessage struct {
- Account string `json:"account"`
- Konnector string `json:"konnector"`
- FolderToSave string `json:"folder_to_save"`
- DefaultFolderPath string `json:"default_folder_path"`
- AccountDeleted bool `json:"account_deleted"`
+// KonnectorMessage is the message structure sent to the konnector worker.
+type KonnectorMessage struct {
+ Account string `json:"account"` // Account is the identifier of the account
+ Konnector string `json:"konnector"` // Konnector is the slug of the konnector
+ FolderToSave string `json:"folder_to_save"` // FolderToSave is the identifier of the folder
+ AccountDeleted bool `json:"account_deleted,omitempty"`
// Data contains the original value of the message, even fields that are not
// part of our message definition.
data json.RawMessage
}
-func (m *konnectorMessage) ToJSON() string {
+func (m *KonnectorMessage) ToJSON() string {
return string(m.data)
}
-// konnectorResult stores the result of a konnector execution.
-// TODO: remove this type kept for retro-compatibility.
-type konnectorResult struct {
- DocID string `json:"_id,omitempty"`
- DocRev string `json:"_rev,omitempty"`
- CreatedAt time.Time `json:"last_execution"`
- LastSuccess time.Time `json:"last_success"`
- Account string `json:"account"`
- AccountRev string `json:"account_rev"`
- State jobs.State `json:"state"`
- Error string `json:"error"`
+func (m *KonnectorMessage) updateFolderToSave(dir string) {
+ m.FolderToSave = dir
+ var d map[string]interface{}
+ json.Unmarshal(m.data, &d)
+ d["folder_to_save"] = dir
+ m.data, _ = json.Marshal(d)
}
// beforeHookKonnector skips jobs from trigger that are failing on certain
// errors.
-func beforeHookKonnector(req *jobs.JobRequest) (bool, error) {
- if req.Manual || req.Trigger == nil {
+func beforeHookKonnector(job *jobs.Job) (bool, error) {
+ var msg KonnectorMessage
+
+ if err := json.Unmarshal(job.Message, &msg); err == nil {
+ inst, err := instance.Get(job.DomainName())
+ if err != nil {
+ return false, err
+ }
+ app, err := registry.GetApplication(msg.Konnector, inst.Registries())
+ if err != nil {
+ job.Logger().Warnf("konnector %q could not get application to fetch maintenance status", msg.Konnector)
+ } else if app.MaintenanceActivated {
+ if job.Manual && !app.MaintenanceOptions.FlagDisallowManualExec {
+ return true, nil
+ }
+ job.Logger().Infof("konnector %q has not been triggered because of its maintenance status", msg.Konnector)
+ return false, nil
+ }
+ }
+
+ if job.Manual || job.TriggerID == "" {
return true, nil
}
- trigger := req.Trigger
- state, err := jobs.GetTriggerState(trigger)
+
+ state, err := jobs.GetTriggerState(job, job.TriggerID)
if err != nil {
return false, err
}
@@ -97,17 +112,10 @@ func beforeHookKonnector(req *jobs.JobRequest) (bool, error) {
return true, nil
}
-func (r *konnectorResult) ID() string { return r.DocID }
-func (r *konnectorResult) Rev() string { return r.DocRev }
-func (r *konnectorResult) DocType() string { return consts.KonnectorResults }
-func (r *konnectorResult) Clone() couchdb.Doc { c := *r; return &c }
-func (r *konnectorResult) SetID(id string) { r.DocID = id }
-func (r *konnectorResult) SetRev(rev string) { r.DocRev = rev }
-
func (w *konnectorWorker) PrepareWorkDir(ctx *jobs.WorkerContext, i *instance.Instance) (string, error) {
var err error
var data json.RawMessage
- var msg konnectorMessage
+ var msg KonnectorMessage
if err = ctx.UnmarshalMessage(&data); err != nil {
return "", err
}
@@ -119,7 +127,9 @@ func (w *konnectorWorker) PrepareWorkDir(ctx *jobs.WorkerContext, i *instance.In
slug := msg.Konnector
w.slug = slug
w.msg = &msg
- w.man, err = apps.GetKonnectorBySlug(i, slug)
+
+ w.man, err = apps.GetKonnectorBySlugAndUpdate(i, slug,
+ i.AppsCopier(apps.Konnector), i.Registries())
if err == apps.ErrNotFound {
return "", jobs.ErrBadTrigger{Err: err}
} else if err != nil {
@@ -128,8 +138,8 @@ func (w *konnectorWorker) PrepareWorkDir(ctx *jobs.WorkerContext, i *instance.In
// Check that the associated account is present.
var account *accounts.Account
- if msg.Account != "" && !ctx.Manual() && !msg.AccountDeleted {
- account := &accounts.Account{}
+ if msg.Account != "" && !msg.AccountDeleted {
+ account = &accounts.Account{}
err = couchdb.GetDoc(i, consts.Accounts, msg.Account, account)
if couchdb.IsNotFoundError(err) {
return "", jobs.ErrBadTrigger{Err: err}
@@ -166,8 +176,13 @@ func (w *konnectorWorker) PrepareWorkDir(ctx *jobs.WorkerContext, i *instance.In
}
// Create the folder in which the konnector has the right to write.
- if err = ensureFolderToSave(i, &msg, slug, account); err != nil {
- return "", nil
+ if err = w.ensureFolderToSave(ctx, i, account); err != nil {
+ return "", err
+ }
+
+ // Make sure the konnector can write to this folder
+ if err = w.ensurePermissions(i); err != nil {
+ return "", err
}
// If we get the AccountDeleted flag on, we check if the konnector manifest
@@ -190,14 +205,55 @@ func (w *konnectorWorker) PrepareWorkDir(ctx *jobs.WorkerContext, i *instance.In
// ensureFolderToSave tries hard to give a folder to the konnector where it can
// write its files if it needs to do so.
-func ensureFolderToSave(inst *instance.Instance, msg *konnectorMessage, slug string, account *accounts.Account) error {
+func (w *konnectorWorker) ensureFolderToSave(ctx *jobs.WorkerContext, inst *instance.Instance, account *accounts.Account) error {
fs := inst.VFS()
+ msg := w.msg
+
+ var normalizedFolderPath string
+ if account != nil {
+ admin := inst.Translate("Tree Administrative")
+ r := strings.NewReplacer("&", "_", "/", "_", "\\", "_", "#", "_",
+ ",", "_", "+", "_", "(", "_", ")", "_", "$", "_", "@", "_", "~",
+ "_", "%", "_", ".", "_", "'", "_", "\"", "_", ":", "_", "*", "_",
+ "?", "_", "<", "_", ">", "_", "{", "_", "}", "_")
+ accountName := r.Replace(account.Name)
+ normalizedFolderPath = fmt.Sprintf("/%s/%s/%s", admin, strings.Title(w.slug), accountName)
+
+ // This is code to handle legacy: if the konnector does not actually require
+ // a directory (for instance because it does not upload files), but a folder
+ // has been created in the past by the stack which is still empty, then we
+ // delete it.
+ if msg.FolderToSave == "" && account.FolderPath == "" && account.Basic.FolderPath == "" {
+ if dir, errp := fs.DirByPath(normalizedFolderPath); errp == nil {
+ if account.Name == "" {
+ innerDirPath := path.Join(normalizedFolderPath, strings.Title(w.slug))
+ if innerDir, errp := fs.DirByPath(innerDirPath); errp == nil {
+ if isEmpty, _ := innerDir.IsEmpty(fs); isEmpty {
+ w.Logger(ctx).Warnf("Deleting empty directory for konnector: %q:%q", innerDir.ID(), normalizedFolderPath)
+ fs.DeleteDirDoc(innerDir)
+ }
+ }
+ }
+ if isEmpty, _ := dir.IsEmpty(fs); isEmpty {
+ w.Logger(ctx).Warnf("Deleting empty directory for konnector: %q:%q", dir.ID(), normalizedFolderPath)
+ fs.DeleteDirDoc(dir)
+ }
+ }
+ }
+ }
// 1. Check if the folder identified by its ID exists
if msg.FolderToSave != "" {
dir, err := fs.DirByID(msg.FolderToSave)
if err == nil {
if !strings.HasPrefix(dir.Fullpath, vfs.TrashDirName) {
+ if len(dir.ReferencedBy) == 0 {
+ dir.AddReferencedBy(couchdb.DocReference{
+ Type: consts.Konnectors,
+ ID: consts.Konnectors + "/" + w.slug,
+ })
+ couchdb.UpdateDoc(inst, dir)
+ }
return nil
}
} else if !os.IsNotExist(err) {
@@ -206,7 +262,7 @@ func ensureFolderToSave(inst *instance.Instance, msg *konnectorMessage, slug str
}
// 2. Check if the konnector has a reference to a folder
- start := []string{consts.Konnectors, consts.Konnectors + "/" + slug}
+ start := []string{consts.Konnectors, consts.Konnectors + "/" + w.slug}
end := []string{start[0], start[1], couchdb.MaxString}
req := &couchdb.ViewRequest{
StartKey: start,
@@ -227,39 +283,74 @@ func ensureFolderToSave(inst *instance.Instance, msg *konnectorMessage, slug str
}
}
if count == 1 {
- msg.FolderToSave = dirID
+ msg.updateFolderToSave(dirID)
return nil
}
}
- // 3. Recreate the folder
+ // 3 Check if a folder should be created
if account == nil {
return nil
}
- admin := inst.Translate("Tree Administrative")
- r := strings.NewReplacer("&", "_", "/", "_", "\\", "_", "#", "_",
- ",", "_", "+", "_", "(", "_", ")", "_", "$", "_", "@", "_", "~",
- "_", "%", "_", ".", "_", "'", "_", "\"", "_", ":", "_", "*", "_",
- "?", "_", "<", "_", ">", "_", "{", "_", "}", "_")
- accountName := r.Replace(account.Name)
- folderPath := fmt.Sprintf("/%s/%s/%s", admin, strings.Title(slug), accountName)
+ if msg.FolderToSave == "" && account.FolderPath == "" && account.Basic.FolderPath == "" {
+ return nil
+ }
+
+ // 4. Recreate the folder
+ folderPath := account.FolderPath
+ if folderPath == "" {
+ folderPath = account.Basic.FolderPath
+ }
+ if folderPath == "" {
+ folderPath = normalizedFolderPath
+ }
+
dir, err := vfs.MkdirAll(fs, folderPath)
if err != nil {
log := inst.Logger().WithField("nspace", "konnector")
log.Warnf("Can't create the default folder %s: %s", folderPath, err)
return err
}
- msg.FolderToSave = dir.ID()
+ msg.updateFolderToSave(dir.ID())
if len(dir.ReferencedBy) == 0 {
dir.AddReferencedBy(couchdb.DocReference{
Type: consts.Konnectors,
- ID: consts.Konnectors + "/" + slug,
+ ID: consts.Konnectors + "/" + w.slug,
})
couchdb.UpdateDoc(inst, dir)
}
return nil
}
+// ensurePermissions checks that the konnector has the permissions to write
+// files in the folder referenced by the konnector, and adds the permission if
+// needed.
+func (w *konnectorWorker) ensurePermissions(inst *instance.Instance) error {
+ perms, err := permissions.GetForKonnector(inst, w.slug)
+ if err != nil {
+ return err
+ }
+ value := consts.Konnectors + "/" + w.slug
+ for _, rule := range perms.Permissions {
+ if rule.Type == consts.Files && rule.Selector == couchdb.SelectorReferencedBy {
+ for _, val := range rule.Values {
+ if val == value {
+ return nil
+ }
+ }
+ }
+ }
+ rule := permissions.Rule{
+ Type: consts.Files,
+ Title: "referenced folders",
+ Description: "folders referenced by the konnector",
+ Selector: couchdb.SelectorReferencedBy,
+ Values: []string{value},
+ }
+ perms.Permissions = append(perms.Permissions, rule)
+ return couchdb.UpdateDoc(inst, perms)
+}
+
func copyFiles(workFS afero.Fs, fileServer apps.FileServer, slug, version string) error {
files, err := fileServer.FilesList(slug, version)
if err != nil {
@@ -420,115 +511,11 @@ func (w *konnectorWorker) Error(i *instance.Instance, err error) error {
}
func (w *konnectorWorker) Commit(ctx *jobs.WorkerContext, errjob error) error {
- if w.msg == nil {
- return nil
- }
-
- // TODO: remove this retro-compatibility block
- // <<<<<<<<<<<<<
- accountID := w.msg.Account
- domain := ctx.Domain()
-
- inst, err := instance.Get(domain)
- if err != nil {
- return err
- }
-
- lastResult := &konnectorResult{}
- err = couchdb.GetDoc(inst, consts.KonnectorResults, w.slug, lastResult)
- if err != nil {
- if !couchdb.IsNotFoundError(err) {
- return err
- }
- lastResult = nil
- }
-
- var state jobs.State
- var errstr string
- var lastSuccess time.Time
- if errjob != nil {
- if lastResult != nil {
- lastSuccess = lastResult.LastSuccess
- }
- errstr = errjob.Error()
- state = jobs.Errored
+ log := w.Logger(ctx).WithField("account_id", w.msg.Account)
+ if errjob == nil {
+ log.Info("Konnector success")
} else {
- lastSuccess = time.Now()
- state = jobs.Done
- }
-
- result := &konnectorResult{
- DocID: w.slug,
- Account: accountID,
- CreatedAt: time.Now(),
- LastSuccess: lastSuccess,
- State: state,
- Error: errstr,
+ log.Infof("Konnector failure: %s", errjob)
}
- if lastResult == nil {
- err = couchdb.CreateNamedDocWithDB(inst, result)
- } else {
- result.SetRev(lastResult.Rev())
- err = couchdb.UpdateDoc(inst, result)
- }
- return err
- // >>>>>>>>>>>>>
-
- // if errjob == nil {
- // return nil
- // }
-
- // triggerID, ok := ctx.TriggerID()
- // if !ok {
- // return nil
- // }
-
- // sched := jobs.System()
- // t, err := sched.GetTrigger(ctx.Domain(), triggerID)
- // if err != nil {
- // return err
- // }
-
- // lastJob, err := scheduler.GetLastJob(t)
- // // if it is the first try we do not take into account an error, we bail.
- // if err == scheduler.ErrNotFoundTrigger {
- // return nil
- // }
- // if err != nil {
- // return err
- // }
-
- // // if the last job was already errored, we bail.
- // if lastJob.State == jobs.Errored {
- // return nil
- // }
-
- // i, err := instance.Get(ctx.Domain())
- // if err != nil {
- // return err
- // }
-
- // konnectorURL := i.SubDomain(consts.CollectSlug)
- // konnectorURL.Fragment = "/category/all/" + w.slug
- // mail := mails.Options{
- // Mode: mails.ModeNoReply,
- // TemplateName: "konnector_error",
- // TemplateValues: map[string]string{
- // "KonnectorName": w.slug,
- // "KonnectorPage": konnectorURL.String(),
- // },
- // }
-
- // msg, err := jobs.NewMessage(&mail)
- // if err != nil {
- // return err
- // }
-
- // ctx.Logger().Info("Konnector has failed definitively, should send mail.", mail)
- // _, err = jobs.System().PushJob(&jobs.JobRequest{
- // Domain: ctx.Domain(),
- // WorkerType: "sendmail",
- // Message: msg,
- // })
- // return err
+ return nil
}
diff --git a/pkg/workers/exec/service.go b/pkg/workers/exec/service.go
index 5fa6c7df8c3..1b195f9ad2a 100644
--- a/pkg/workers/exec/service.go
+++ b/pkg/workers/exec/service.go
@@ -42,7 +42,8 @@ func (w *serviceWorker) PrepareWorkDir(ctx *jobs.WorkerContext, i *instance.Inst
slug := opts.Slug
name := opts.Name
- man, err := apps.GetWebappBySlug(i, slug)
+ man, err := apps.GetWebappBySlugAndUpdate(i, slug,
+ i.AppsCopier(apps.Webapp), i.Registries())
if err != nil {
if err == apps.ErrNotFound {
err = jobs.ErrBadTrigger{Err: err}
diff --git a/pkg/workers/mails/mail_templates.go b/pkg/workers/mails/mail_templates.go
index 88de09d4bb5..708f7020a4e 100644
--- a/pkg/workers/mails/mail_templates.go
+++ b/pkg/workers/mails/mail_templates.go
@@ -292,11 +292,6 @@ func init() {
},
Outro: "Mail Reset Passphrase Outro",
},
- {
- Name: "konnector_error",
- Subject: "Mail Konnector Error Subject",
- Intro: "Mail Konnector Error Intro",
- },
{
Name: "archiver",
Subject: "Mail Archive Subject",
@@ -377,10 +372,15 @@ func init() {
Intro: "Notifications Disk Quota Intro",
Actions: []MailAction{
{
- Instructions: "Notifications Disk Quota instruction",
- Text: "Notifications Disk Quota text",
+ Instructions: "Notifications Disk Quota offers instruction",
+ Text: "Notifications Disk Quota offers text",
Link: "{{.OffersLink}}",
},
+ {
+ Instructions: "Notifications Disk Quota free instructions",
+ Text: "Notifications Disk Quota free text",
+ Link: "{{.CozyDriveLink}}",
+ },
},
},
}}
diff --git a/pkg/workers/move/export.go b/pkg/workers/move/export.go
index f43f71bcabd..dd28810b683 100644
--- a/pkg/workers/move/export.go
+++ b/pkg/workers/move/export.go
@@ -490,18 +490,18 @@ func Export(i *instance.Instance, opts ExportOptions, archiver Archiver) (export
size += n
if !opts.WithoutFiles {
- var root *vfs.TreeFile
- root, err = i.VFS().BuildTree()
+ var tree *vfs.Tree
+ tree, err = i.VFS().BuildTree()
if err != nil {
return
}
- n, err = writeDoc("", "files-index", root, createdAt, tw)
+ n, err = writeDoc("", "files-index", tree.Root, createdAt, tw)
if err != nil {
return
}
size += n
- exportDoc.PartsCursors, _ = splitFilesIndex(root, nil, nil, exportDoc.PartsSize, exportDoc.PartsSize)
+ exportDoc.PartsCursors, _ = splitFilesIndex(tree.Root, nil, nil, exportDoc.PartsSize, exportDoc.PartsSize)
}
n, err = exportDocs(i, opts.WithDoctypes, createdAt, tw)
diff --git a/pkg/workers/updates/updates.go b/pkg/workers/updates/updates.go
index a9fbdc6c47d..4743529e24c 100644
--- a/pkg/workers/updates/updates.go
+++ b/pkg/workers/updates/updates.go
@@ -231,11 +231,7 @@ func UpdateInstance(ctx *jobs.WorkerContext, inst *instance.Instance, opts *Opti
}
func installerPush(inst *instance.Instance, insc chan *apps.Installer, errc chan *updateError, opts *Options) {
- registries, err := inst.Registries()
- if err != nil {
- errc <- &updateError{step: "Registries", reason: err}
- return
- }
+ registries := inst.Registries()
var g sync.WaitGroup
g.Add(2)
@@ -340,10 +336,11 @@ func createInstaller(inst *instance.Instance, registries []*url.URL, man apps.Ma
}
return apps.NewInstaller(inst, inst.AppsCopier(man.AppType()),
&apps.InstallerOptions{
- Operation: apps.Update,
- Manifest: man,
- Registries: registries,
- SourceURL: sourceURL,
+ Operation: apps.Update,
+ Manifest: man,
+ Registries: registries,
+ SourceURL: sourceURL,
+ PermissionsAcked: true,
},
)
}
diff --git a/scripts/build.sh b/scripts/build.sh
index 18ad0ebdf6a..843e93af0cd 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -23,12 +23,12 @@ echo_wrn() {
}
usage() {
- echo -e "Usage: ${1} [release] [install] [deploy] [docker-dev] [assets] [clean]"
+ echo -e "Usage: ${1} [release] [install] [deploy] [dev] [assets] [clean]"
echo -e "\nCommands:\n"
echo -e " release builds a release of the current working-tree"
echo -e " install builds a release and install it the GOPATH"
echo -e " deploy builds a release of the current working-tree and deploys it"
- echo -e " docker-dev builds a cozy-app-dev docker image"
+ echo -e " dev builds a dev version"
echo -e " assets move and download all the required assets (see: ./assets/externals)"
echo -e " clean remove all generated files from the working-tree"
@@ -182,33 +182,13 @@ do_deploy() {
do_assets() {
tx --root "${WORK_DIR}" pull -a || echo "Do you have configured transifex?"
printf "executing go generate...\n"
- go get -u github.com/cozy/statik
+ go get -u github.com/cozy/cozy-stack/pkg/statik
pushd "${WORK_DIR}" > /dev/null
go generate ./web
popd > /dev/null
echo "ok"
}
-do_docker_dev_image() {
- docker_work_dir="${WORK_DIR}/.docker-work"
- mkdir "${docker_work_dir}"
-
- trap 'trap - SIGTERM && rm -rf "${docker_work_dir}" > /dev/null -- -${$}' SIGINT SIGTERM EXIT
-
- cp "${WORK_DIR}/scripts/Dockerfile" "${docker_work_dir}"
- cp "${WORK_DIR}/scripts/docker-entrypoint.sh" "${docker_work_dir}"
- cp "${WORK_DIR}/scripts/cozy-app-dev.sh" "${docker_work_dir}"
-
- export GOOS=linux
- export GOARCH=amd64
- export COZY_ENV=development
- do_build "${docker_work_dir}/cozy-stack"
-
- docker build -t cozy/cozy-app-dev "${docker_work_dir}"
-
- rm -rf "${docker_work_dir}"
-}
-
do_clean() {
find "${WORK_DIR}" -name "cozy-stack-*" -print -delete
}
@@ -241,8 +221,8 @@ case "${1}" in
do_assets
;;
- docker-dev)
- do_docker_dev_image
+ dev)
+ COZY_ENV=development do_build scripts/cozy-stack
;;
*)
diff --git a/scripts/cozy-app-dev.sh b/scripts/cozy-app-dev.sh
index 6ff1da1013f..eb231a80599 100755
--- a/scripts/cozy-app-dev.sh
+++ b/scripts/cozy-app-dev.sh
@@ -6,6 +6,7 @@ set -m
[ -z "${COZY_STACK_HOST}" ] && COZY_STACK_HOST="cozy.tools"
[ -z "${COZY_STACK_PORT}" ] && COZY_STACK_PORT="8080"
[ -z "${COZY_STACK_PASS}" ] && COZY_STACK_PASS="cozy"
+[ -z "${COZY_STACK_ADMIN_PORT}" ] && COZY_STACK_ADMIN_PORT="6060"
[ -z "${COUCHDB_URL}" ] && COUCHDB_URL="http://localhost:5984/"
if [ -d "${COZY_STACK_PATH}" ] && [ -f "${COZY_STACK_PATH}/cozy-stack" ]; then
@@ -37,6 +38,9 @@ usage() {
echo -e "\n COZY_STACK_PORT"
echo -e " specify the port on which the cozy-stack is listening."
echo -e " default: 8080."
+ echo -e "\n COZY_STACK_ADMIN_PORT"
+ echo -e " specify the admin port on which the cozy-stack is listening."
+ echo -e " default: 6060."
echo -e "\n COZY_STACK_PASS"
echo -e " specify the password to register the instance with."
echo -e " default: cozy."
@@ -102,6 +106,7 @@ do_start() {
--appdir "${appdir}" \
--host "${COZY_STACK_HOST}" \
--port "${COZY_STACK_PORT}" \
+ --admin-port "${COZY_STACK_ADMIN_PORT}" \
--couchdb-url "${COUCHDB_URL}" \
--mail-host "${COZY_STACK_HOST}" \
--mail-port 1025 \
diff --git a/scripts/lint.sh b/scripts/lint.sh
index 24f09d20576..16e81152f4d 100755
--- a/scripts/lint.sh
+++ b/scripts/lint.sh
@@ -6,6 +6,7 @@ if git grep -l \
-e 'github.com/dgrijalva/jwt-go' \
-e 'github.com/labstack/echo' \
-e 'github.com/spf13/afero' \
+ -e 'github.com/cozy/statik' \
-- '*.go'; then
echo "Forbidden packages"
exit 1
diff --git a/scripts/release.sh b/scripts/release.sh
index 73d8b03c039..792c67cd738 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -5,9 +5,16 @@ RELEASE="$(git describe --tags)"
go get -u -v ./...
+GOOS=linux GOARCH=amd64 ./scripts/build.sh dev
+docker build -t "cozy/cozy-app-dev:${RELEASE}" scripts
+docker push "cozy/cozy-app-dev:${RELEASE}"
+docker tag "cozy/cozy-app-dev:${RELEASE}" cozy/cozy-app-dev
+docker push cozy/cozy-app-dev
+
GOOS=linux GOARCH=amd64 ./scripts/build.sh release
GOOS=linux GOARCH=arm ./scripts/build.sh release
GOOS=freebsd GOARCH=amd64 ./scripts/build.sh release
+
rm -f "*.sha256"
sha256sum cozy-stack-*-${RELEASE} > "cozy-stack-${RELEASE}.sha256"
diff --git a/tests/clone/generate_tests.go b/tests/clone/generate_tests.go
index 097d7421371..505eacccd6b 100644
--- a/tests/clone/generate_tests.go
+++ b/tests/clone/generate_tests.go
@@ -148,6 +148,9 @@ import (
`)
for _, info := range infos {
fmt.Printf("\t\"%s\"\n", info.PkgPath)
+ if info.PkgPath == "github.com/cozy/cozy-stack/pkg/config_dyn" {
+ fmt.Printf("\t\"github.com/cozy/cozy-stack/pkg/statik/fs\"\n")
+ }
}
fmt.Printf(")\n\n")
diff --git a/web/apps/apps.go b/web/apps/apps.go
index fda5e99c58e..ae6c6e369a0 100644
--- a/web/apps/apps.go
+++ b/web/apps/apps.go
@@ -42,7 +42,7 @@ func (man *apiApp) Links() *jsonapi.LinksList {
case (*apps.WebappManifest):
route = "/apps/"
if app.Icon != "" {
- links.Icon = "/apps/" + app.Slug() + "/icon"
+ links.Icon = "/apps/" + app.Slug() + "/icon/" + app.Version()
}
if (app.State() == apps.Ready || app.State() == apps.Installed) &&
app.Instance != nil {
@@ -51,7 +51,7 @@ func (man *apiApp) Links() *jsonapi.LinksList {
case (*apps.KonnManifest):
route = "/konnectors/"
if app.Icon != "" {
- links.Icon = "/konnectors/" + app.Slug() + "/icon"
+ links.Icon = "/konnectors/" + app.Slug() + "/icon/" + app.Version()
}
links.Perms = "/permissions/konnectors/" + app.Slug()
}
@@ -101,15 +101,11 @@ func installHandler(installerType apps.AppType) echo.HandlerFunc {
if err := middlewares.AllowInstallApp(c, installerType, permissions.POST); err != nil {
return err
}
- registries, err := instance.Registries()
- if err != nil {
- return err
- }
var overridenParameters *json.RawMessage
if p := c.QueryParam("Parameters"); p != "" {
var v json.RawMessage
- if err = json.Unmarshal([]byte(p), &v); err != nil {
+ if err := json.Unmarshal([]byte(p), &v); err != nil {
return echo.NewHTTPError(http.StatusBadRequest)
}
overridenParameters = &v
@@ -130,7 +126,7 @@ func installHandler(installerType apps.AppType) echo.HandlerFunc {
SourceURL: c.QueryParam("Source"),
Slug: slug,
Deactivated: c.QueryParam("Deactivated") == "true",
- Registries: registries,
+ Registries: instance.Registries(),
OverridenParameters: overridenParameters,
},
@@ -159,15 +155,11 @@ func updateHandler(installerType apps.AppType) echo.HandlerFunc {
if err := middlewares.AllowInstallApp(c, installerType, permissions.POST); err != nil {
return err
}
- registries, err := instance.Registries()
- if err != nil {
- return err
- }
var overridenParameters *json.RawMessage
if p := c.QueryParam("Parameters"); p != "" {
var v json.RawMessage
- if err = json.Unmarshal([]byte(p), &v); err != nil {
+ if err := json.Unmarshal([]byte(p), &v); err != nil {
return echo.NewHTTPError(http.StatusBadRequest)
}
overridenParameters = &v
@@ -188,7 +180,7 @@ func updateHandler(installerType apps.AppType) echo.HandlerFunc {
Type: installerType,
SourceURL: c.QueryParam("Source"),
Slug: slug,
- Registries: registries,
+ Registries: instance.Registries(),
PermissionsAcked: permissionsAcked,
OverridenParameters: overridenParameters,
@@ -219,16 +211,12 @@ func deleteHandler(installerType apps.AppType) echo.HandlerFunc {
if err := middlewares.AllowInstallApp(c, installerType, permissions.DELETE); err != nil {
return err
}
- registries, err := instance.Registries()
- if err != nil {
- return err
- }
inst, err := apps.NewInstaller(instance, instance.AppsCopier(installerType),
&apps.InstallerOptions{
Operation: apps.Delete,
Type: installerType,
Slug: slug,
- Registries: registries,
+ Registries: instance.Registries(),
},
)
if err != nil {
@@ -332,13 +320,20 @@ func iconHandler(appType apps.AppType) echo.HandlerFunc {
return func(c echo.Context) error {
instance := middlewares.GetInstance(c)
slug := c.Param("slug")
+ version := c.Param("version")
app, err := apps.GetBySlug(instance, slug, appType)
if err != nil {
return err
}
- if err = middlewares.Allow(c, permissions.GET, app); err != nil {
- return err
+ if !middlewares.IsLoggedIn(c) {
+ return echo.NewHTTPError(http.StatusUnauthorized, "Not logged in")
+ }
+
+ if version != "" {
+ // The maximum cache-control recommanded is one year :
+ // https://www.ietf.org/rfc/rfc2616.txt
+ c.Response().Header().Set("Cache-Control", "max-age=31536000, immutable")
}
var fs apps.FileServer
@@ -369,6 +364,7 @@ func WebappsRoutes(router *echo.Group) {
router.PUT("/:slug", updateHandler(apps.Webapp))
router.DELETE("/:slug", deleteHandler(apps.Webapp))
router.GET("/:slug/icon", iconHandler(apps.Webapp))
+ router.GET("/:slug/icon/:version", iconHandler(apps.Webapp))
}
// KonnectorRoutes sets the routing for the konnectors service
@@ -379,6 +375,7 @@ func KonnectorRoutes(router *echo.Group) {
router.PUT("/:slug", updateHandler(apps.Konnector))
router.DELETE("/:slug", deleteHandler(apps.Konnector))
router.GET("/:slug/icon", iconHandler(apps.Konnector))
+ router.GET("/:slug/icon/:version", iconHandler(apps.Konnector))
}
func wrapAppsError(err error) error {
diff --git a/web/apps/apps_test.go b/web/apps/apps_test.go
index b41e5ad55c3..e041d23d9b4 100644
--- a/web/apps/apps_test.go
+++ b/web/apps/apps_test.go
@@ -223,8 +223,8 @@ func TestServeWithAnIntents(t *testing.T) {
res, err := doGet(path, true)
assert.NoError(t, err)
assert.Equal(t, 200, res.StatusCode)
- h := res.Header.Get(echo.HeaderXFrameOptions)
- assert.Equal(t, "ALLOW-FROM https://test-app.cozywithapps.example.net/", h)
+ h := res.Header.Get(echo.HeaderContentSecurityPolicy)
+ assert.Contains(t, h, "frame-ancestors 'self' https://test-app.cozywithapps.example.net/;")
}
func TestServeAppsWithACode(t *testing.T) {
@@ -326,7 +326,7 @@ func TestListApps(t *testing.T) {
related := links["related"].(string)
assert.Equal(t, "https://cozywithapps-mini.example.net/", related)
icon := links["icon"].(string)
- assert.Equal(t, "/apps/mini/icon", icon)
+ assert.Equal(t, "/apps/mini/icon/", icon)
}
func TestIconForApp(t *testing.T) {
diff --git a/web/apps/serve.go b/web/apps/serve.go
index ad1e8ae1dcb..074a1136622 100644
--- a/web/apps/serve.go
+++ b/web/apps/serve.go
@@ -2,7 +2,6 @@ package apps
import (
"bytes"
- "fmt"
"html/template"
"io/ioutil"
"net/http"
@@ -58,16 +57,14 @@ func Serve(c echo.Context) error {
return c.Redirect(http.StatusFound, redirect)
}
- app, err := apps.GetWebappBySlug(i, slug)
+ app, err := apps.GetWebappBySlugAndUpdate(i, slug,
+ i.AppsCopier(apps.Webapp), i.Registries())
if err != nil {
- switch err {
- case apps.ErrNotFound:
- return echo.NewHTTPError(http.StatusNotFound, "Application not found")
- case apps.ErrInvalidSlugName:
- return echo.NewHTTPError(http.StatusBadRequest, err.Error())
- default:
- return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
+ // Used for the "collect" => "home" renaming
+ if err == apps.ErrNotFound && slug == consts.CollectSlug {
+ return c.Redirect(http.StatusMovedPermanently, i.DefaultRedirection().String())
}
+ return err
}
switch app.State() {
@@ -103,8 +100,7 @@ func handleIntent(c echo.Context, i *instance.Instance, slug, intentID string) {
return
}
from := i.SubDomain(parts[1]).String()
- hdr := fmt.Sprintf("%s %s", middlewares.XFrameAllowFrom, from)
- c.Response().Header().Set(echo.HeaderXFrameOptions, hdr)
+ middlewares.AppendCSPRule(c, "frame-ancestors", from)
}
// ServeAppFile will serve the requested file using the specified application
@@ -224,9 +220,10 @@ func ServeAppFile(c echo.Context, i *instance.Instance, fs apps.FileServer, app
return tmpl.Execute(res, echo.Map{
"Token": token,
"Domain": i.ContextualDomain(),
+ "ContextName": i.ContextName,
"Locale": i.Locale,
"AppSlug": app.Slug(),
- "AppName": app.Name,
+ "AppName": app.NameLocalized(i.Locale),
"AppEditor": app.Editor,
"AppNamePrefix": app.NamePrefix,
"IconPath": app.Icon,
@@ -282,46 +279,39 @@ func deleteAppCookie(c echo.Context, i *instance.Instance, slug string) error {
return c.Redirect(http.StatusFound, u)
}
-var assetHelper func(domain, file string) string
var clientTemplate *template.Template
var barTemplate *template.Template
func init() {
- h := statik.NewHandler(statik.Options{Prefix: "/assets"})
- assetHelper = func(domain, file string) string {
- file = h.AssetPath(file)
- if domain != "" {
- return "//" + domain + file
- }
- return file
- }
-
funcsMap := template.FuncMap{
"split": strings.Split,
- "asset": assetHelper,
+ "asset": statik.AssetPath,
}
clientTemplate = template.Must(template.New("cozy-client-js").Funcs(funcsMap).Parse(`` +
- ``,
+ ``,
))
barTemplate = template.Must(template.New("cozy-bar").Funcs(funcsMap).Parse(`
-
-
+
+
{{if .LoggedIn}}
{{range .Warnings}}
{{end}}
{{end}}
-`,
+`,
))
}
func cozyclientjs(i *instance.Instance) template.HTML {
buf := new(bytes.Buffer)
- err := clientTemplate.Execute(buf, echo.Map{"Domain": i.ContextualDomain()})
+ err := clientTemplate.Execute(buf, echo.Map{
+ "Domain": i.ContextualDomain(),
+ "ContextName": i.ContextName,
+ })
if err != nil {
- return template.HTML("")
+ panic(err)
}
return template.HTML(buf.String()) // #nosec
}
@@ -329,12 +319,13 @@ func cozyclientjs(i *instance.Instance) template.HTML {
func cozybar(i *instance.Instance, loggedIn bool) template.HTML {
buf := new(bytes.Buffer)
err := barTemplate.Execute(buf, echo.Map{
- "Domain": i.ContextualDomain(),
- "Warnings": i.Warnings(),
- "LoggedIn": loggedIn,
+ "Domain": i.ContextualDomain(),
+ "Warnings": i.Warnings(),
+ "ContextName": i.ContextName,
+ "LoggedIn": loggedIn,
})
if err != nil {
- return template.HTML("")
+ panic(err)
}
return template.HTML(buf.String()) // #nosec
}
diff --git a/web/auth/auth.go b/web/auth/auth.go
index dd273353c89..24902436115 100644
--- a/web/auth/auth.go
+++ b/web/auth/auth.go
@@ -269,7 +269,14 @@ func login(c echo.Context) error {
var clientID string
if inst.HasDomain(redirect.Host) && redirect.Path == "/auth/authorize" {
- clientID = redirect.Query().Get("client_id")
+ // NOTE: the login scope is used by external clients for authentication.
+ // Typically, these clients are used for internal purposes, like
+ // authenticating to an external system via the cozy. For these clients
+ // we do not push a "client" notification, we only store a new login
+ // history.
+ if redirect.Query().Get("scope") != oauth.ScopeLogin {
+ clientID = redirect.Query().Get("client_id")
+ }
}
if err = sessions.StoreNewLoginEntry(inst, sessionID, clientID, c.Request(), true); err != nil {
diff --git a/web/data/accounts.go b/web/data/accounts.go
index bdd84bb958d..f952badac84 100644
--- a/web/data/accounts.go
+++ b/web/data/accounts.go
@@ -163,7 +163,7 @@ func encryptMap(m map[string]interface{}) (encrypted bool) {
if err == nil {
encrypted = true
}
- case "secret", "dob", "code", "answer", "access_token", "refresh_token":
+ case "secret", "dob", "code", "answer", "access_token", "refresh_token", "appSecret":
cloned[k+"_encrypted"], err = accounts.EncryptCredentialsData(v)
if err == nil {
encrypted = true
diff --git a/web/dev.go b/web/dev.go
index fd4fd2909ff..65f27852a29 100644
--- a/web/dev.go
+++ b/web/dev.go
@@ -15,7 +15,10 @@ import (
// "text/plain".
func devMailsHandler(c echo.Context) error {
name := c.Param("name")
- locale := statik.GetLanguageFromHeader(c.Request().Header)
+ locale := c.QueryParam("locale")
+ if locale == "" {
+ locale = statik.GetLanguageFromHeader(c.Request().Header)
+ }
recipientName := c.QueryParam("RecipientName")
if recipientName == "" {
diff --git a/web/errors/errors.go b/web/errors/errors.go
index f43d880d7a9..237e3c08e43 100644
--- a/web/errors/errors.go
+++ b/web/errors/errors.go
@@ -6,6 +6,7 @@ import (
"os"
"strings"
+ "github.com/cozy/cozy-stack/pkg/apps"
"github.com/cozy/cozy-stack/pkg/config"
"github.com/cozy/cozy-stack/pkg/couchdb"
"github.com/cozy/cozy-stack/pkg/instance"
@@ -102,11 +103,19 @@ func HTMLErrorHandler(err error, c echo.Context) {
}
var title, value string
- if err == instance.ErrNotFound {
+ switch err {
+ case instance.ErrNotFound:
status = http.StatusNotFound
title = "Error Instance not found Title"
value = "Error Instance not found Message"
+ case apps.ErrNotFound:
+ status = http.StatusNotFound
+ title = "Error Application not found Title"
+ value = "Error Application not found Message"
+ case apps.ErrInvalidSlugName:
+ status = http.StatusBadRequest
}
+
if title == "" {
if status >= 500 {
title = "Error Internal Server Error Title"
@@ -130,10 +139,19 @@ func HTMLErrorHandler(err error, c echo.Context) {
if ok {
domain = i.ContextualDomain()
}
+
+ var actionTitle, actionURL string
+ if ok && err == apps.ErrNotFound {
+ actionURL = i.DefaultRedirection().String()
+ actionTitle = "Error Application not found Action"
+ }
+
err = c.Render(status, "error.html", echo.Map{
- "Domain": domain,
- "ErrorTitle": title,
- "Error": value,
+ "Domain": domain,
+ "ErrorTitle": title,
+ "Error": value,
+ "ActionTitle": actionTitle,
+ "ActionURL": actionURL,
})
} else {
err = c.String(status, fmt.Sprintf("%v", he.Message))
diff --git a/web/files/files.go b/web/files/files.go
index daaecea5741..179801f0060 100644
--- a/web/files/files.go
+++ b/web/files/files.go
@@ -18,6 +18,7 @@ import (
"strings"
"time"
+ "github.com/cozy/cozy-stack/pkg/config"
"github.com/cozy/cozy-stack/pkg/consts"
"github.com/cozy/cozy-stack/pkg/couchdb"
pkgperm "github.com/cozy/cozy-stack/pkg/permissions"
@@ -29,8 +30,8 @@ import (
"github.com/cozy/cozy-stack/web/permissions"
web_utils "github.com/cozy/cozy-stack/web/utils"
+ statikFS "github.com/cozy/cozy-stack/pkg/statik/fs"
"github.com/cozy/echo"
- statikFS "github.com/cozy/statik/fs"
)
type docPatch struct {
@@ -571,11 +572,11 @@ func serveThumbnailPlaceholder(res http.ResponseWriter, req *http.Request, doc *
if !utils.IsInArray(format, thumbnail.FormatsNames) {
return echo.NewHTTPError(http.StatusNotFound, "Format does not exist")
}
- f, ok := statikFS.Get("/placeholders/thumbnail-" + format + ".png")
+ f, ok := statikFS.Get("/placeholders/thumbnail-"+format+".png", "")
if !ok {
return os.ErrNotExist
}
- etag := f.Etag()
+ etag := f.Etag
if web_utils.CheckPreconditions(res, req, etag) {
return nil
}
@@ -605,7 +606,7 @@ func sendFileFromPath(c echo.Context, path string, checkPermission bool) error {
} else if !checkPermission {
// Allow some files to be displayed by the browser in the client-side apps
if doc.Mime == "text/plain" || doc.Class == "image" || doc.Class == "audio" || doc.Class == "video" || doc.Mime == "application/pdf" {
- c.Response().Header().Del(echo.HeaderXFrameOptions)
+ middlewares.AppendCSPRule(c, "frame-ancestors", "*")
}
}
err = vfs.ServeFileContent(instance.VFS(), doc, disposition, c.Request(), c.Response())
@@ -956,6 +957,46 @@ func FindFilesMango(c echo.Context) error {
}
+func fsckHandler(c echo.Context) error {
+ instance := middlewares.GetInstance(c)
+ cacheStorage := config.GetConfig().CacheStorage
+
+ if err := middlewares.AllowWholeType(c, permissions.GET, consts.Files); err != nil {
+ return err
+ }
+
+ noCache, _ := strconv.ParseBool(c.QueryParam("NoCache"))
+ key := "fsck:" + instance.DBPrefix()
+ if !noCache {
+ if r, ok := cacheStorage.GetCompressed(key); ok {
+ return c.Stream(http.StatusOK, echo.MIMEApplicationJSON, r)
+ }
+ }
+
+ logs := make([]*vfs.FsckLog, 0)
+ err := instance.VFS().Fsck(func(log *vfs.FsckLog) {
+ switch log.Type {
+ case vfs.ContentMismatch:
+ logs = append(logs, log)
+ }
+ })
+ if err != nil {
+ return err
+ }
+
+ logsData, err := json.Marshal(logs)
+ if err != nil {
+ return err
+ }
+
+ if !noCache {
+ expiration := utils.DurationFuzzing(3*30*24*time.Hour, 0.10)
+ cacheStorage.SetCompressed(key, logsData, expiration)
+ }
+
+ return c.JSONBlob(http.StatusOK, logsData)
+}
+
// Routes sets the routing for the files service
func Routes(router *echo.Group) {
router.HEAD("/download", ReadFileContentFromPathHandler)
@@ -997,6 +1038,7 @@ func Routes(router *echo.Group) {
router.DELETE("/trash/:file-id", DestroyFileHandler)
router.DELETE("/:file-id", TrashHandler)
+ router.GET("/fsck", fsckHandler)
}
// WrapVfsError returns a formatted error from a golang error emitted by the vfs
diff --git a/web/files/files_test.go b/web/files/files_test.go
index ceacef86732..b1eaa3f5857 100644
--- a/web/files/files_test.go
+++ b/web/files/files_test.go
@@ -865,7 +865,7 @@ func TestDownloadFileByIDSuccess(t *testing.T) {
res2, resbody := download(t, "/files/download/"+fileID, "")
assert.Equal(t, 200, res2.StatusCode)
assert.True(t, strings.HasPrefix(res2.Header.Get("Content-Disposition"), "inline"))
- assert.True(t, strings.Contains(res2.Header.Get("Content-Disposition"), "filename=downloadme1"))
+ assert.True(t, strings.Contains(res2.Header.Get("Content-Disposition"), `filename="downloadme1"`))
assert.True(t, strings.HasPrefix(res2.Header.Get("Content-Type"), "text/plain"))
assert.NotEmpty(t, res2.Header.Get("Etag"))
assert.Equal(t, res2.Header.Get("Etag")[:1], `"`)
@@ -882,7 +882,7 @@ func TestDownloadFileByPathSuccess(t *testing.T) {
res2, resbody := download(t, "/files/download?Dl=1&Path="+url.QueryEscape("/downloadme2"), "")
assert.Equal(t, 200, res2.StatusCode)
assert.True(t, strings.HasPrefix(res2.Header.Get("Content-Disposition"), "attachment"))
- assert.True(t, strings.Contains(res2.Header.Get("Content-Disposition"), "filename=downloadme2"))
+ assert.True(t, strings.Contains(res2.Header.Get("Content-Disposition"), `filename="downloadme2"`))
assert.True(t, strings.HasPrefix(res2.Header.Get("Content-Type"), "text/plain"))
assert.Equal(t, res2.Header.Get("Content-Length"), "3")
assert.Equal(t, res2.Header.Get("Accept-Ranges"), "bytes")
@@ -1067,7 +1067,7 @@ func TestArchiveCreateAndDownload(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 200, res2.StatusCode)
disposition := res2.Header.Get("Content-Disposition")
- assert.Equal(t, `attachment; filename=archive.zip`, disposition)
+ assert.Equal(t, `attachment; filename="archive.zip"`, disposition)
}
func TestFileCreateAndDownloadByPath(t *testing.T) {
@@ -1101,14 +1101,14 @@ func TestFileCreateAndDownloadByPath(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 200, res2.StatusCode)
disposition := res2.Header.Get("Content-Disposition")
- assert.Equal(t, `inline; filename=todownload2steps`, disposition)
+ assert.Equal(t, `inline; filename="todownload2steps"`, disposition)
downloadURL := ts.URL + data["links"].(map[string]interface{})["related"].(string) + "?Dl=1"
res3, err := http.Get(downloadURL)
assert.NoError(t, err)
assert.Equal(t, 200, res3.StatusCode)
disposition = res3.Header.Get("Content-Disposition")
- assert.Equal(t, `attachment; filename=todownload2steps`, disposition)
+ assert.Equal(t, `attachment; filename="todownload2steps"`, disposition)
}
func TestFileCreateAndDownloadByID(t *testing.T) {
@@ -1141,7 +1141,7 @@ func TestFileCreateAndDownloadByID(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 200, res2.StatusCode)
disposition := res2.Header.Get("Content-Disposition")
- assert.Equal(t, `inline; filename=todownload2stepsbis`, disposition)
+ assert.Equal(t, `inline; filename="todownload2stepsbis"`, disposition)
}
func TestHeadDirOrFileNotFound(t *testing.T) {
@@ -1745,8 +1745,8 @@ func TestMain(m *testing.M) {
token = tok
ts = setup.GetTestServer("/files", Routes, func(r *echo.Echo) *echo.Echo {
secure := middlewares.Secure(&middlewares.SecureConfig{
- CSPDefaultSrc: []middlewares.CSPSource{middlewares.CSPSrcSelf},
- XFrameOptions: middlewares.XFrameDeny,
+ CSPDefaultSrc: []middlewares.CSPSource{middlewares.CSPSrcSelf},
+ CSPFrameAncestors: []middlewares.CSPSource{middlewares.CSPSrcNone},
})
r.Use(secure)
return r
diff --git a/web/instances/client.go b/web/instances/client.go
index 64ed1f2438c..428433c30ad 100644
--- a/web/instances/client.go
+++ b/web/instances/client.go
@@ -2,6 +2,7 @@ package instances
import (
"net/http"
+ "strconv"
"time"
"github.com/cozy/cozy-stack/pkg/instance"
@@ -65,13 +66,34 @@ func registerClient(c echo.Context) error {
if err != nil {
return wrapError(err)
}
+ allowLoginScope, err := strconv.ParseBool(c.QueryParam("AllowLoginScope"))
+ if err != nil {
+ return wrapError(err)
+ }
+
client := oauth.Client{
- RedirectURIs: []string{c.QueryParam("RedirectURI")},
- ClientName: c.QueryParam("ClientName"),
- SoftwareID: c.QueryParam("SoftwareID"),
+ RedirectURIs: []string{c.QueryParam("RedirectURI")},
+ ClientName: c.QueryParam("ClientName"),
+ SoftwareID: c.QueryParam("SoftwareID"),
+ AllowLoginScope: allowLoginScope,
}
if regErr := client.Create(in); regErr != nil {
return c.String(http.StatusBadRequest, regErr.Description)
}
return c.JSON(http.StatusOK, client)
}
+
+func findClientBySoftwareID(c echo.Context) error {
+ domain := c.QueryParam("domain")
+ softwareID := c.QueryParam("software_id")
+
+ inst, err := instance.Get(domain)
+ if err != nil {
+ return err
+ }
+ client, err := oauth.FindClientBySoftwareID(inst, softwareID)
+ if err != nil {
+ return err
+ }
+ return c.JSON(http.StatusOK, client)
+}
diff --git a/web/instances/instances.go b/web/instances/instances.go
index 588cfdda44f..d3cbc398f1e 100644
--- a/web/instances/instances.go
+++ b/web/instances/instances.go
@@ -11,11 +11,14 @@ import (
"github.com/cozy/cozy-stack/pkg/accounts"
"github.com/cozy/cozy-stack/pkg/apps"
+ "github.com/cozy/cozy-stack/pkg/config"
+ "github.com/cozy/cozy-stack/pkg/config_dyn"
"github.com/cozy/cozy-stack/pkg/consts"
"github.com/cozy/cozy-stack/pkg/couchdb"
"github.com/cozy/cozy-stack/pkg/instance"
"github.com/cozy/cozy-stack/pkg/jobs"
"github.com/cozy/cozy-stack/pkg/prefixer"
+ "github.com/cozy/cozy-stack/pkg/statik/fs"
"github.com/cozy/cozy-stack/pkg/utils"
"github.com/cozy/cozy-stack/pkg/vfs"
"github.com/cozy/cozy-stack/pkg/workers/updates"
@@ -184,23 +187,38 @@ func deleteHandler(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
}
-func fsckHandler(c echo.Context) error {
+func fsckHandler(c echo.Context) (err error) {
domain := c.Param("domain")
i, err := instance.Get(domain)
if err != nil {
return wrapError(err)
}
- prune, _ := strconv.ParseBool(c.QueryParam("Prune"))
- dryRun, _ := strconv.ParseBool(c.QueryParam("DryRun"))
- fs := i.VFS()
- logbook, err := fs.Fsck(vfs.FsckOptions{
- Prune: prune,
- DryRun: dryRun,
- })
- if err != nil {
- return wrapError(err)
+
+ indexIntegrityCheck, _ := strconv.ParseBool(c.QueryParam("IndexIntegrity"))
+
+ logCh := make(chan *vfs.FsckLog)
+ go func() {
+ fs := i.VFS()
+ if indexIntegrityCheck {
+ err = fs.CheckIndexIntegrity(func(log *vfs.FsckLog) { logCh <- log })
+ } else {
+ err = fs.Fsck(func(log *vfs.FsckLog) { logCh <- log })
+ }
+ close(logCh)
+ }()
+
+ w := c.Response().Writer
+ w.WriteHeader(200)
+ encoder := json.NewEncoder(w)
+ for log := range logCh {
+ if errenc := encoder.Encode(log); errenc != nil {
+ return errenc
+ }
+ if f, ok := w.(http.Flusher); ok {
+ f.Flush()
+ }
}
- return c.JSON(http.StatusOK, logbook)
+ return err
}
func rebuildRedis(c echo.Context) error {
@@ -220,6 +238,28 @@ func rebuildRedis(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
}
+// Renders the assets list loaded in memory and served by the cozy
+func assetsInfos(c echo.Context) error {
+ assetsMap := make(map[string][]*fs.Asset)
+ fs.Foreach(func(name, context string, f *fs.Asset) {
+ assetsMap[context] = append(assetsMap[context], f)
+ })
+ return c.JSON(http.StatusOK, assetsMap)
+}
+
+func addAssets(c echo.Context) error {
+ var unmarshaledAssets []fs.AssetOption
+ if err := json.NewDecoder(c.Request().Body).Decode(&unmarshaledAssets); err != nil {
+ return err
+ }
+ cacheStorage := config.GetConfig().CacheStorage
+ err := fs.RegisterCustomExternals(cacheStorage, unmarshaledAssets, 0 /* = retry count */)
+ if err != nil {
+ return c.JSON(http.StatusBadRequest, echo.Map{"error": err.Error()})
+ }
+ return config_dyn.UpdateAssetsList()
+}
+
func cleanOrphanAccounts(c echo.Context) error {
type result struct {
Result string `json:"result"`
@@ -374,6 +414,37 @@ func updatesHandler(c echo.Context) error {
return c.JSON(http.StatusOK, job)
}
+func showPrefix(c echo.Context) error {
+ domain := c.Param("domain")
+
+ instance, err := instance.Get(domain)
+ if err != nil {
+ return err
+ }
+
+ return c.JSON(http.StatusOK, instance.DBPrefix())
+}
+
+func getSwiftBucketName(c echo.Context) error {
+ domain := c.Param("domain")
+
+ instance, err := instance.Get(domain)
+
+ if err != nil {
+ return err
+ }
+ type swifter interface {
+ ContainersNames() map[string]string
+ }
+
+ var containersNames map[string]string
+ if obj, ok := instance.VFS().(swifter); ok {
+ containersNames = obj.ContainersNames()
+ }
+
+ return c.JSON(http.StatusOK, containersNames)
+}
+
func wrapError(err error) error {
switch err {
case instance.ErrNotFound:
@@ -406,9 +477,14 @@ func Routes(router *echo.Group) {
router.GET("/:domain/fsck", fsckHandler)
router.POST("/updates", updatesHandler)
router.POST("/token", createToken)
+ router.GET("/oauth_client", findClientBySoftwareID)
router.POST("/oauth_client", registerClient)
router.POST("/:domain/export", exporter)
router.POST("/:domain/import", importer)
router.POST("/:domain/orphan_accounts", cleanOrphanAccounts)
router.POST("/redis", rebuildRedis)
+ router.GET("/assets", assetsInfos)
+ router.POST("/assets", addAssets)
+ router.GET("/:domain/prefix", showPrefix)
+ router.GET("/:domain/swift-prefix", getSwiftBucketName)
}
diff --git a/web/jobs/jobs.go b/web/jobs/jobs.go
index 0dc5057b803..7ea673989da 100644
--- a/web/jobs/jobs.go
+++ b/web/jobs/jobs.go
@@ -20,7 +20,7 @@ import (
multierror "github.com/hashicorp/go-multierror"
// import workers
- _ "github.com/cozy/cozy-stack/pkg/workers/exec"
+ "github.com/cozy/cozy-stack/pkg/workers/exec"
_ "github.com/cozy/cozy-stack/pkg/workers/indexupdate"
_ "github.com/cozy/cozy-stack/pkg/workers/log"
_ "github.com/cozy/cozy-stack/pkg/workers/mails"
@@ -232,7 +232,7 @@ func getTrigger(c echo.Context) error {
return err
}
tInfos := t.Infos()
- tInfos.CurrentState, err = jobs.GetTriggerState(t)
+ tInfos.CurrentState, err = jobs.GetTriggerState(t, t.ID())
if err != nil {
return wrapJobsError(err)
}
@@ -257,7 +257,7 @@ func getTriggerState(c echo.Context) error {
}
}
- state, err := jobs.GetTriggerState(t)
+ state, err := jobs.GetTriggerState(t, t.ID())
if err != nil {
return wrapJobsError(err)
}
@@ -272,9 +272,7 @@ func extractKonnectorPermissions(c echo.Context, i *instance.Instance, t jobs.Tr
if err != nil {
return
}
- var msg struct {
- Konnector string `json:"konnector"`
- }
+ var msg exec.KonnectorMessage
if err = t.Infos().Message.Unmarshal(&msg); err != nil {
return
}
@@ -329,7 +327,7 @@ func getTriggerJobs(c echo.Context) error {
return err
}
- js, err := jobs.GetJobs(t, limit)
+ js, err := jobs.GetJobs(t, t.ID(), limit)
if err != nil {
return wrapJobsError(err)
}
@@ -405,7 +403,7 @@ func getAllTriggers(c echo.Context) error {
for _, t := range ts {
tInfos := t.Infos()
if workerType == "" || tInfos.WorkerType == workerType {
- tInfos.CurrentState, err = jobs.GetTriggerState(t)
+ tInfos.CurrentState, err = jobs.GetTriggerState(t, t.ID())
if err != nil {
return wrapJobsError(err)
}
diff --git a/web/middlewares/secure.go b/web/middlewares/secure.go
index 873db00b107..fa001ca9fa3 100644
--- a/web/middlewares/secure.go
+++ b/web/middlewares/secure.go
@@ -6,60 +6,53 @@ import (
"strings"
"time"
+ "github.com/cozy/cozy-stack/pkg/config"
"github.com/cozy/echo"
)
type (
- // XFrameOption type for the values of the X-Frame-Options header.
- XFrameOption string
-
// CSPSource type are the different types of CSP headers sources definitions.
// Each source type defines a different acess policy.
CSPSource int
// SecureConfig defines the config for Secure middleware.
SecureConfig struct {
- HSTSMaxAge time.Duration
- CSPDefaultSrc []CSPSource
- CSPScriptSrc []CSPSource
- CSPFrameSrc []CSPSource
- CSPConnectSrc []CSPSource
- CSPFontSrc []CSPSource
- CSPImgSrc []CSPSource
- CSPManifestSrc []CSPSource
- CSPMediaSrc []CSPSource
- CSPObjectSrc []CSPSource
- CSPStyleSrc []CSPSource
- CSPWorkerSrc []CSPSource
+ HSTSMaxAge time.Duration
- CSPDefaultSrcWhitelist string
- CSPScriptSrcWhitelist string
- CSPFrameSrcWhitelist string
- CSPConnectSrcWhitelist string
- CSPFontSrcWhitelist string
- CSPImgSrcWhitelist string
- CSPManifestSrcWhitelist string
- CSPMediaSrcWhitelist string
- CSPObjectSrcWhitelist string
- CSPStyleSrcWhitelist string
- CSPWorkerSrcWhitelist string
+ CSPDefaultSrc []CSPSource
+ CSPScriptSrc []CSPSource
+ CSPFrameSrc []CSPSource
+ CSPConnectSrc []CSPSource
+ CSPFontSrc []CSPSource
+ CSPImgSrc []CSPSource
+ CSPManifestSrc []CSPSource
+ CSPMediaSrc []CSPSource
+ CSPObjectSrc []CSPSource
+ CSPStyleSrc []CSPSource
+ CSPWorkerSrc []CSPSource
+ CSPFrameAncestors []CSPSource
- XFrameOptions XFrameOption
- XFrameAllowed string
+ CSPDefaultSrcWhitelist string
+ CSPScriptSrcWhitelist string
+ CSPFrameSrcWhitelist string
+ CSPConnectSrcWhitelist string
+ CSPFontSrcWhitelist string
+ CSPImgSrcWhitelist string
+ CSPManifestSrcWhitelist string
+ CSPMediaSrcWhitelist string
+ CSPObjectSrcWhitelist string
+ CSPStyleSrcWhitelist string
+ CSPWorkerSrcWhitelist string
+ CSPFrameAncestorsWhitelist string
}
)
const (
- // XFrameDeny is the DENY option of the X-Frame-Options header.
- XFrameDeny XFrameOption = "DENY"
- // XFrameSameOrigin is the SAMEORIGIN option of the X-Frame-Options header.
- XFrameSameOrigin = "SAMEORIGIN"
- // XFrameAllowFrom is the ALLOW-FROM option of the X-Frame-Options header. It
- // should be used along with the XFrameAllowed field of SecureConfig.
- XFrameAllowFrom = "ALLOW-FROM"
-
// CSPSrcSelf is the 'self' option of a CSP source.
CSPSrcSelf CSPSource = iota
+ // CSPSrcNone is the 'none' option. It denies all domains as an eligible
+ // source.
+ CSPSrcNone
// CSPSrcData is the 'data:' option of a CSP source.
CSPSrcData
// CSPSrcBlob is the 'blob:' option of a CSP source.
@@ -89,16 +82,6 @@ func Secure(conf *SecureConfig) echo.MiddlewareFunc {
conf.HSTSMaxAge.Seconds())
}
- var xFrameHeader string
- switch conf.XFrameOptions {
- case XFrameDeny:
- xFrameHeader = string(XFrameDeny)
- case XFrameSameOrigin:
- xFrameHeader = string(XFrameSameOrigin)
- case XFrameAllowFrom:
- xFrameHeader = fmt.Sprintf("%s %s", XFrameAllowFrom, conf.XFrameAllowed)
- }
-
conf.CSPDefaultSrc, conf.CSPDefaultSrcWhitelist =
validCSPList(conf.CSPDefaultSrc, conf.CSPDefaultSrc, conf.CSPDefaultSrcWhitelist)
conf.CSPScriptSrc, conf.CSPScriptSrcWhitelist =
@@ -132,9 +115,6 @@ func Secure(conf *SecureConfig) echo.MiddlewareFunc {
if isSecure && hstsHeader != "" {
h.Set(echo.HeaderStrictTransportSecurity, hstsHeader)
}
- if xFrameHeader != "" {
- h.Set(echo.HeaderXFrameOptions, xFrameHeader)
- }
var cspHeader string
parent, _, siblings := SplitHost(c.Request().Host)
if len(conf.CSPDefaultSrc) > 0 {
@@ -170,6 +150,9 @@ func Secure(conf *SecureConfig) echo.MiddlewareFunc {
if len(conf.CSPWorkerSrc) > 0 {
cspHeader += makeCSPHeader(parent, siblings, "worker-src", conf.CSPWorkerSrcWhitelist, conf.CSPWorkerSrc, isSecure)
}
+ if len(conf.CSPFrameAncestors) > 0 {
+ cspHeader += makeCSPHeader(parent, siblings, "frame-ancestors", conf.CSPFrameAncestorsWhitelist, conf.CSPFrameAncestors, isSecure)
+ }
if cspHeader != "" {
h.Set(echo.HeaderContentSecurityPolicy, cspHeader)
}
@@ -187,7 +170,9 @@ func validCSPList(sources, defaults []CSPSource, whitelist string) ([]CSPSource,
if err != nil {
continue
}
- u.Scheme = "https"
+ if !config.IsDevRelease() {
+ u.Scheme = "https"
+ }
if u.Path == "" {
u.Path = "/"
}
@@ -229,6 +214,8 @@ func makeCSPHeader(parent, siblings, header, cspWhitelist string, sources []CSPS
switch src {
case CSPSrcSelf:
headers[i] = "'self'"
+ case CSPSrcNone:
+ headers[i] = "'none'"
case CSPSrcData:
headers[i] = "data:"
case CSPSrcBlob:
@@ -261,3 +248,27 @@ func makeCSPHeader(parent, siblings, header, cspWhitelist string, sources []CSPS
}
return header + " " + strings.Join(headers, " ") + ";"
}
+
+// AppendCSPRule allows to patch inline the CSP headers to add a new rule.
+func AppendCSPRule(c echo.Context, ruleType string, appendedValues ...string) {
+ currentRules := c.Response().Header().Get(echo.HeaderContentSecurityPolicy)
+ newRules := appendCSPRule(currentRules, ruleType, appendedValues...)
+ c.Response().Header().Set(echo.HeaderContentSecurityPolicy, newRules)
+}
+
+func appendCSPRule(currentRules, ruleType string, appendedValues ...string) (newRules string) {
+ ruleIndex := strings.Index(currentRules, ruleType)
+ if ruleIndex >= 0 {
+ ruleTerminationIndex := strings.Index(currentRules[ruleIndex:], ";")
+ if ruleTerminationIndex <= 0 {
+ return
+ }
+ ruleFields := strings.Fields(currentRules[ruleIndex : ruleIndex+ruleTerminationIndex])
+ ruleFields = append(ruleFields, appendedValues...)
+ newRules = currentRules[:ruleIndex] + strings.Join(ruleFields, " ") +
+ currentRules[ruleIndex+ruleTerminationIndex:]
+ } else {
+ newRules = currentRules + ruleType + " " + strings.Join(appendedValues, " ") + ";"
+ }
+ return
+}
diff --git a/web/middlewares/secure_test.go b/web/middlewares/secure_test.go
index adedd78dbc0..c34f8ec9052 100644
--- a/web/middlewares/secure_test.go
+++ b/web/middlewares/secure_test.go
@@ -61,36 +61,25 @@ func TestSecureMiddlewareCSP(t *testing.T) {
assert.Equal(t, "script-src https://*.cozy.local;frame-src *;connect-src https://cozy.local 'self';", rec3.Header().Get(echo.HeaderContentSecurityPolicy))
}
-func TestSecureMiddlewareXFrame(t *testing.T) {
- e1 := echo.New()
- req1, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil)
- rec1 := httptest.NewRecorder()
- c1 := e1.NewContext(req1, rec1)
- h1 := Secure(&SecureConfig{
- XFrameOptions: XFrameDeny,
- })(echo.NotFoundHandler)
- h1(c1)
+func TestAppendCSPRule(t *testing.T) {
+ r := appendCSPRule("", "frame-ancestors", "new-rule")
+ assert.Equal(t, "frame-ancestors new-rule;", r)
- e2 := echo.New()
- req2, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil)
- rec2 := httptest.NewRecorder()
- c2 := e2.NewContext(req2, rec2)
- h2 := Secure(&SecureConfig{
- XFrameOptions: XFrameSameOrigin,
- })(echo.NotFoundHandler)
- h2(c2)
+ r = appendCSPRule("frame-ancestors;", "frame-ancestors", "new-rule")
+ assert.Equal(t, "frame-ancestors new-rule;", r)
- e3 := echo.New()
- req3, _ := http.NewRequest(echo.GET, "http://app.cozy.local/", nil)
- rec3 := httptest.NewRecorder()
- c3 := e3.NewContext(req3, rec3)
- h3 := Secure(&SecureConfig{
- XFrameOptions: XFrameAllowFrom,
- XFrameAllowed: "allowed.foobar",
- })(echo.NotFoundHandler)
- h3(c3)
+ r = appendCSPRule("frame-ancestors 1 2 3 ;", "frame-ancestors", "new-rule")
+ assert.Equal(t, "frame-ancestors 1 2 3 new-rule;", r)
+
+ r = appendCSPRule("frame-ancestors 1 2 3 ;", "frame-ancestors", "new-rule", "new-rule-2")
+ assert.Equal(t, "frame-ancestors 1 2 3 new-rule new-rule-2;", r)
+
+ r = appendCSPRule("script '*'; frame-ancestors 'self';", "frame-ancestors", "new-rule")
+ assert.Equal(t, "script '*'; frame-ancestors 'self' new-rule;", r)
+
+ r = appendCSPRule("script '*'; frame-ancestors 'self'; plop plop;", "frame-ancestors", "new-rule")
+ assert.Equal(t, "script '*'; frame-ancestors 'self' new-rule; plop plop;", r)
- assert.Equal(t, "DENY", rec1.Header().Get(echo.HeaderXFrameOptions))
- assert.Equal(t, "SAMEORIGIN", rec2.Header().Get(echo.HeaderXFrameOptions))
- assert.Equal(t, "ALLOW-FROM allowed.foobar", rec3.Header().Get(echo.HeaderXFrameOptions))
+ r = appendCSPRule("script '*'; toto;", "frame-ancestors", "new-rule")
+ assert.Equal(t, "script '*'; toto;frame-ancestors new-rule;", r)
}
diff --git a/web/registry/registry.go b/web/registry/registry.go
index de15c85dcce..49111bce3c8 100644
--- a/web/registry/registry.go
+++ b/web/registry/registry.go
@@ -16,7 +16,7 @@ const (
perms
)
-func proxyReq(auth authType, cacheControl registry.CacheControl) echo.HandlerFunc {
+func proxyReq(auth authType, clientPermanentCache bool, proxyCacheControl registry.CacheControl) echo.HandlerFunc {
return func(c echo.Context) error {
i := middlewares.GetInstance(c)
switch auth {
@@ -32,18 +32,17 @@ func proxyReq(auth authType, cacheControl registry.CacheControl) echo.HandlerFun
default:
panic("unknown authType")
}
- registries, err := i.Registries()
- if err != nil {
- return err
- }
req := c.Request()
- resp, err := registry.Proxy(req, registries, cacheControl)
+ proxyResp, err := registry.Proxy(req, i.Registries(), proxyCacheControl)
if err != nil {
return err
}
- defer resp.Body.Close()
- contentType := resp.Header.Get("content-type")
- return c.Stream(resp.StatusCode, contentType, resp.Body)
+ defer proxyResp.Body.Close()
+ if clientPermanentCache {
+ c.Response().Header().Set("Cache-Control", "max-age=31536000, immutable")
+ }
+ contentType := proxyResp.Header.Get("content-type")
+ return c.Stream(proxyResp.StatusCode, contentType, proxyResp.Body)
}
}
@@ -53,12 +52,8 @@ func proxyListReq(c echo.Context) error {
if err != nil || pdoc.Type != permissions.TypeWebapp {
return echo.NewHTTPError(http.StatusForbidden)
}
- registries, err := i.Registries()
- if err != nil {
- return err
- }
req := c.Request()
- list, err := registry.ProxyList(req, registries)
+ list, err := registry.ProxyList(req, i.Registries())
if err != nil {
return err
}
@@ -69,11 +64,11 @@ func proxyListReq(c echo.Context) error {
func Routes(router *echo.Group) {
router.GET("", proxyListReq)
router.GET("/", proxyListReq)
- router.GET("/:app", proxyReq(perms, registry.WithCache))
- router.GET("/:app/icon", proxyReq(authed, registry.NoCache))
- router.GET("/:app/screenshots/*", proxyReq(authed, registry.NoCache))
- router.GET("/:app/:version/icon", proxyReq(authed, registry.NoCache))
- router.GET("/:app/:version/screenshots/*", proxyReq(authed, registry.NoCache))
- router.GET("/:app/:version", proxyReq(perms, registry.WithCache))
- router.GET("/:app/:channel/latest", proxyReq(perms, registry.WithCache))
+ router.GET("/:app", proxyReq(perms, false, registry.WithCache))
+ router.GET("/:app/icon", proxyReq(authed, false, registry.NoCache))
+ router.GET("/:app/screenshots/*", proxyReq(authed, false, registry.NoCache))
+ router.GET("/:app/:version/icon", proxyReq(authed, true, registry.NoCache))
+ router.GET("/:app/:version/screenshots/*", proxyReq(authed, true, registry.NoCache))
+ router.GET("/:app/:version", proxyReq(perms, true, registry.WithCache))
+ router.GET("/:app/:channel/latest", proxyReq(perms, false, registry.WithCache))
}
diff --git a/web/routing.go b/web/routing.go
index bb78f0e23f4..f0482909cdb 100644
--- a/web/routing.go
+++ b/web/routing.go
@@ -59,12 +59,13 @@ func SetupAppsHandler(appsHandler echo.HandlerFunc) echo.HandlerFunc {
}
if !config.GetConfig().CSPDisabled {
secure := middlewares.Secure(&middlewares.SecureConfig{
- HSTSMaxAge: hstsMaxAge,
- CSPDefaultSrc: []middlewares.CSPSource{middlewares.CSPSrcSelf, middlewares.CSPSrcParent, middlewares.CSPSrcWS},
- CSPStyleSrc: []middlewares.CSPSource{middlewares.CSPUnsafeInline},
- CSPFontSrc: []middlewares.CSPSource{middlewares.CSPSrcData},
- CSPImgSrc: []middlewares.CSPSource{middlewares.CSPSrcData, middlewares.CSPSrcBlob},
- CSPFrameSrc: []middlewares.CSPSource{middlewares.CSPSrcSiblings},
+ HSTSMaxAge: hstsMaxAge,
+ CSPDefaultSrc: []middlewares.CSPSource{middlewares.CSPSrcSelf, middlewares.CSPSrcParent, middlewares.CSPSrcWS},
+ CSPStyleSrc: []middlewares.CSPSource{middlewares.CSPUnsafeInline},
+ CSPFontSrc: []middlewares.CSPSource{middlewares.CSPSrcData},
+ CSPImgSrc: []middlewares.CSPSource{middlewares.CSPSrcData, middlewares.CSPSrcBlob},
+ CSPFrameSrc: []middlewares.CSPSource{middlewares.CSPSrcSiblings},
+ CSPFrameAncestors: []middlewares.CSPSource{middlewares.CSPSrcSelf},
CSPDefaultSrcWhitelist: config.GetConfig().CSPWhitelist["default"],
CSPImgSrcWhitelist: config.GetConfig().CSPWhitelist["img"] + " " + cspImgSrcWhitelist,
@@ -72,8 +73,6 @@ func SetupAppsHandler(appsHandler echo.HandlerFunc) echo.HandlerFunc {
CSPConnectSrcWhitelist: config.GetConfig().CSPWhitelist["connect"] + " " + cspScriptSrcWhitelist,
CSPStyleSrcWhitelist: config.GetConfig().CSPWhitelist["style"],
CSPFontSrcWhitelist: config.GetConfig().CSPWhitelist["font"],
-
- XFrameOptions: middlewares.XFrameSameOrigin,
})
mws = append([]echo.MiddlewareFunc{secure}, mws...)
}
@@ -113,9 +112,9 @@ func SetupRoutes(router *echo.Echo) error {
if !config.GetConfig().CSPDisabled {
secure := middlewares.Secure(&middlewares.SecureConfig{
- HSTSMaxAge: hstsMaxAge,
- CSPDefaultSrc: []middlewares.CSPSource{middlewares.CSPSrcSelf},
- XFrameOptions: middlewares.XFrameDeny,
+ HSTSMaxAge: hstsMaxAge,
+ CSPDefaultSrc: []middlewares.CSPSource{middlewares.CSPSrcSelf},
+ CSPFrameAncestors: []middlewares.CSPSource{middlewares.CSPSrcNone},
})
router.Use(secure)
}
diff --git a/web/server.go b/web/server.go
index 1c0ba93f0fb..af7c599bf1f 100644
--- a/web/server.go
+++ b/web/server.go
@@ -24,7 +24,7 @@ import (
"github.com/cozy/echo/middleware"
"github.com/cozy/afero"
- statikFS "github.com/cozy/statik/fs"
+ statikFS "github.com/cozy/cozy-stack/pkg/statik/fs"
)
// ReadHeaderTimeout is the amount of time allowed to read request headers for
diff --git a/web/statik/handler.go b/web/statik/handler.go
index 8504f7123ea..70aa4b3eac5 100644
--- a/web/statik/handler.go
+++ b/web/statik/handler.go
@@ -7,17 +7,18 @@ import (
"io"
"io/ioutil"
"net/http"
+ "net/url"
"os"
"path"
"path/filepath"
"strings"
"github.com/cozy/cozy-stack/pkg/i18n"
+ "github.com/cozy/cozy-stack/pkg/statik/fs"
"github.com/cozy/cozy-stack/pkg/utils"
"github.com/cozy/cozy-stack/web/middlewares"
web_utils "github.com/cozy/cozy-stack/web/utils"
"github.com/cozy/echo"
- "github.com/cozy/statik/fs"
)
var (
@@ -32,12 +33,11 @@ var (
"passphrase_renew.html",
"sharing_discovery.html",
}
+)
- privateAssets = []string{
- "/templates/",
- "/locales/",
- "/placeholders/",
- }
+const (
+ assetsPrefix = "/assets"
+ assetsExtPrefix = "/assets/ext"
)
// AssetRenderer is an interface for both a template renderer and an asset HTTP
@@ -75,13 +75,11 @@ func NewDirRenderer(assetsPath string) (AssetRenderer, error) {
}
t := template.New("stub")
- h := http.StripPrefix("/assets", http.FileServer(dir(assetsPath)))
+ h := http.StripPrefix(assetsPrefix, http.FileServer(dir(assetsPath)))
funcsMap := template.FuncMap{
"t": fmt.Sprintf,
"split": strings.Split,
- "asset": func(domain, file string) string {
- return AssetResolver(domain, path.Join("/assets", file))
- },
+ "asset": assetPath,
}
var err error
@@ -97,16 +95,11 @@ func NewDirRenderer(assetsPath string) (AssetRenderer, error) {
// representation into the binary.
func NewRenderer() (AssetRenderer, error) {
t := template.New("stub")
- h := NewHandler(Options{
- Prefix: "/assets",
- Privates: privateAssets,
- })
+
funcsMap := template.FuncMap{
"t": fmt.Sprintf,
"split": strings.Split,
- "asset": func(domain, file string) string {
- return AssetResolver(domain, h.AssetPath(file))
- },
+ "asset": AssetPath,
}
for _, name := range templatesList {
@@ -124,7 +117,7 @@ func NewRenderer() (AssetRenderer, error) {
}
}
- return &renderer{t: t, Handler: h}, nil
+ return &renderer{t: t, Handler: NewHandler()}, nil
}
type renderer struct {
@@ -148,6 +141,114 @@ func (r *renderer) Render(w io.Writer, name string, data interface{}, c echo.Con
return t.Funcs(funcMap).ExecuteTemplate(w, name, data)
}
+// AssetPath return the fullpath with unique identifier for a given asset file.
+func AssetPath(domain, name string, context ...string) string {
+ f, ok := fs.Get(name, context...)
+ if !ok && len(context) > 0 && context[0] != "" {
+ // fallback on default context if asset is not found in the given one.
+ f, ok = fs.Get(name)
+ if ok {
+ context = nil
+ }
+ }
+ if ok {
+ name = f.NameWithSum
+ }
+ return assetPath(domain, name, context...)
+}
+
+func assetPath(domain, name string, context ...string) string {
+ if len(context) > 0 && context[0] != "" {
+ name = path.Join(assetsExtPrefix, url.PathEscape(context[0]), name)
+ } else {
+ name = path.Join(assetsPrefix, name)
+ }
+ if domain != "" {
+ return "//" + domain + name
+ }
+ return name
+}
+
+// Handler implements http.handler for a subpart of the available assets on a
+// specified prefix.
+type Handler struct{}
+
+// NewHandler returns a new handler
+func NewHandler() Handler {
+ return Handler{}
+}
+
+// ServeHTTP implements the http.Handler interface.
+func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodGet && r.Method != http.MethodHead {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ // The URL path should be formed in one on those forms:
+ // /assets/:file...
+ // /assets/ext/(:context-name)/:file...
+
+ var id, name, context string
+
+ if strings.HasPrefix(r.URL.Path, assetsExtPrefix+"/") {
+ nameWithContext := strings.TrimPrefix(r.URL.Path, assetsExtPrefix+"/")
+ nameWithContextSplit := strings.SplitN(nameWithContext, "/", 2)
+ if len(nameWithContextSplit) != 2 {
+ http.Error(w, "File not found", http.StatusNotFound)
+ return
+ }
+ context = nameWithContextSplit[0]
+ name = nameWithContextSplit[1]
+ } else {
+ name = strings.TrimPrefix(r.URL.Path, assetsPrefix)
+ }
+
+ name, id = ExtractAssetID(name)
+ if len(name) > 0 && name[0] != '/' {
+ name = "/" + name
+ }
+
+ f, ok := fs.Get(name, context)
+ if !ok {
+ http.Error(w, "File not found", http.StatusNotFound)
+ return
+ }
+
+ checkETag := id == ""
+ if checkETag && web_utils.CheckPreconditions(w, r, f.Etag) {
+ return
+ }
+
+ headers := w.Header()
+ headers.Set("Content-Type", f.Mime)
+ headers.Set("Content-Length", f.Size())
+ headers.Add("Vary", "Accept-Encoding")
+
+ acceptsGZIP := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
+ if acceptsGZIP {
+ headers.Set("Content-Encoding", "gzip")
+ headers.Set("Content-Length", f.GzipSize())
+ } else {
+ headers.Set("Content-Length", f.Size())
+ }
+
+ if checkETag {
+ headers.Set("Etag", f.Etag)
+ headers.Set("Cache-Control", "no-cache, public")
+ } else {
+ headers.Set("Cache-Control", "max-age=31536000, public, immutable")
+ }
+
+ if r.Method == http.MethodGet {
+ if acceptsGZIP {
+ io.Copy(w, f.GzipReader())
+ } else {
+ io.Copy(w, f.Reader())
+ }
+ }
+}
+
// GetLanguageFromHeader return the language tag given the Accept-Language
// header.
func GetLanguageFromHeader(header http.Header) (lang string) {
@@ -178,15 +279,6 @@ func GetLanguageFromHeader(header http.Header) (lang string) {
return
}
-// AssetResolver is a template helper returning a complete URL, with domain
-// name, for a given asset path.
-func AssetResolver(domain, file string) string {
- if domain != "" {
- return "//" + domain + file
- }
- return file
-}
-
// ExtractAssetID checks if a long hexadecimal string is contained in given
// file path and returns the original file name and ID (if any). For instance
// =
@@ -210,40 +302,6 @@ func ExtractAssetID(file string) (string, string) {
return file, id
}
-// Handler implements http.Handler for a subpart of the available assets on a
-// specified prefix.
-type Handler struct {
- prefix string
- files map[string]*fs.Asset
-}
-
-// Options contains the different options to create an asset handler.
-type Options struct {
- Prefix string
- Privates []string
-}
-
-// NewHandler returns a new handler
-func NewHandler(opts Options) *Handler {
- files := make(map[string]*fs.Asset)
- fs.Foreach(func(name string, f *fs.Asset) {
- isPrivate := false
- for _, p := range opts.Privates {
- if strings.HasPrefix(name, p) {
- isPrivate = true
- break
- }
- }
- if !isPrivate {
- files[name] = f
- }
- })
- return &Handler{
- prefix: opts.Prefix,
- files: files,
- }
-}
-
func isLongHexString(s string) bool {
if len(s) < 10 {
return false
@@ -259,65 +317,3 @@ func isLongHexString(s string) bool {
}
return true
}
-
-// AssetPath return the fullpath with unique identifier for a given asset file.
-func (h *Handler) AssetPath(file string) string {
- f, ok := h.files[file]
- if !ok {
- return h.prefix + file
- }
- return h.prefix + f.Name()
-}
-
-// ServeHTTP implements the http.Handler interface.
-func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- if r.Method != http.MethodGet && r.Method != http.MethodHead {
- w.WriteHeader(http.StatusMethodNotAllowed)
- return
- }
-
- var id string
- file := strings.TrimPrefix(r.URL.Path, h.prefix)
- file, id = ExtractAssetID(file)
- if len(file) > 0 && file[0] != '/' {
- file = "/" + file
- }
- f, ok := h.files[file]
- if !ok {
- http.Error(w, "File not found", http.StatusNotFound)
- return
- }
-
- checkETag := id == ""
- if checkETag && web_utils.CheckPreconditions(w, r, f.Etag()) {
- return
- }
-
- headers := w.Header()
- headers.Set("Content-Type", f.Mime())
- headers.Set("Content-Length", f.Size())
- headers.Add("Vary", "Accept-Encoding")
-
- acceptsGZIP := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
- if acceptsGZIP {
- headers.Set("Content-Encoding", "gzip")
- headers.Set("Content-Length", f.GzipSize())
- } else {
- headers.Set("Content-Length", f.Size())
- }
-
- if checkETag {
- headers.Set("Etag", f.Etag())
- headers.Set("Cache-Control", "no-cache, public")
- } else {
- headers.Set("Cache-Control", "max-age=31536000, public, immutable")
- }
-
- if r.Method == http.MethodGet {
- if acceptsGZIP {
- io.Copy(w, f.GzipReader())
- } else {
- io.Copy(w, f.Reader())
- }
- }
-}
diff --git a/web/statik/statik.go b/web/statik/statik.go
index d635106864e..61d34d3c428 100644
--- a/web/statik/statik.go
+++ b/web/statik/statik.go
@@ -3,355 +3,412 @@
package statik
import (
- "github.com/cozy/statik/fs"
+ "github.com/cozy/cozy-stack/pkg/statik/fs"
)
func init() {
data := `-----BEGIN COZY ASSET-----
Name: /css/cozy-bar.min.css
-Size: 73037
+Size: 92504
-H4sIAAAAAAAC/+y9/XObSNI4/vv9Ffp+ntq65Dby8erYTt3WKkabJacZogjdrnLP
-/oAQxqDXAmTEuPK/f6t7BgQIJNnJ3t3ek9rK2oaZnp6Zfqen58fucs26cy+7i5yl
-F3fiTbDqdrv3Tnzf7U6d2LvUunr38S5aLx+TyFnFd+toeROtEyfxXkgzz3/5OVkf
-vlH1a3z3+cdu6k3nQfK7DrH+PaH/fqAv3O40aYD4TycKnO50G2d/S6Kt99sP8cZZ
-3Th3iRe9yvtEnr9dONHzOseeu17NnCh7XveZs/K9qLveJotg5T0The00WXzlvl9p
-eqfAi+n/LrDvA/9+Efj3yZPAP7rrVeKtkps///nNLIg3Cye7CVa4OdPF2p2/efCi
-JHCdRddZBP7qZhnMZgvvzdKJ/GDVXXh3yc2FHnnLN1PHnfvReruadTfrOEiC9erG
-9VaJF5VfRd7Gc5Kb1Vr8Vn4XB8y7cdcPXvRvJO+n09ZjGsyS+xsZFuHegw3A37+x
-6DcW/Uos6qyCpYMM1axGOnLcgb1yok6wugtWQeJ9/g9ZzWfOuCQVgqXjezfbaPFi
-5iTODf751/jB/363XLzhwF59+Jkqn7K32vSX3dZl0sr5+aPkGuuHgTpTZ5mukkx/
-cJfuAwl7Kbm9ZrOluzJ//rT59Ovsdqr61+9Zzye3PUYC+Of6M2Uxn72D5/3sffZ2
-/emXxcr5eZj/vXR+2cUfRrPsk2KuiT1UBkZfIbfpjjJ/855pV+67nyTn9u2D++6n
-0Pn1o/5h5G5JOF6Z74bX7yVpR4NeOrH7imnAPxw7xZ/M9Ik94f/yZ7cSI0spNY2P
-98SG96Z414efGb3t7UiA/3j7US8d2Kb0Prv6/sPPb+9n73z/kyGtbBzv7X0Vfl+M
-92k9sOvwewmxzYTY7y8RFl+372/9v/3t5b9cuP1BKEJ13i2kTyO3WPmp+vZ+oiwk
-z5ZWg9CU32dv5x9GM4qr/q4PlIDUsKcCknGqqFBGQtj7hNz2pIndh/eZeLfDn+HQ
-P6QMKaO37sOHcJdOfv24PkJ5u3w851aqw08Hdj+Df14AsNIHV/20+uCvSxTwOwmQ
-PzwtuCEJ5+qnXybZe6b93bzt/cdIhdug539NyXDbSBe/pxnxBbr6j0I8H8Nx9tF4
-3/8/Rjzb7kMQb53FIrsPZjOvyWcuvAtnGq8X28T7/4LlZh0lzip5M11HMy+6kUqP
-uHV+IV2qkbcsPRem+uELcEDuFuv0hmNQerNxZrNg5VfB3weJ1403juvdrNZp5GxK
-L91FsLmJPDd5IYZ51fLzZa1Td+Mk9zfBKvaSF7r0Xek1LNF9MGtgisfcfVutV96b
-hyAOpsEiSDIxD+joRdG6gV0e3fViHd38z52uzJRZqWHqRKtg5R/2uJl6d+vIO+k8
-Cjcx4kuNfuKht3Rx9brmQT6NJ4MzeDIwf55tPv38cf1hZO5oYPrOu39sPin3Uv73
-bLlYzKT3D54hBYKGOS+FnP8+Fbz5fjtV9IUZ8L8Hv76Xp+/G1+byH8qnX/SHT++G
-gfnzx2zyi84+La+zqS0Fs5/f309XNJ78+nHx91spswzfB6Vq3c6DD/7aN29LPLVc
-xFNDCkxpIpP5MPt4awKfBbZt6nSkpSTsK5Y9j4lt6oPQZdSeyNborUHCuTwIxwo1
-fN26TXck9LeUuSoJx7JpmDoNNInavZ1lm9BXG4SuRu2JIt7pluFLJDTrcAlhPTYI
-xxkxhvLA6EtkpGU0HOo0e2sQ1pMGYU8hbCiRIN1Rw9yS0GSEuZJpkJRkmkJsItNw
-EhN7yAawHwbZ0VGPEcPcUrvHqN3XEG6mpcToMWKPfdswNWukycQgKskALtkSo5cS
-1pfNPoH12xI214ndy+p9Seirg3AuWYbLrFGOU1+y7IluAtxbDd7tKBsCTrtBaCrU
-mKtmP80se7wlhrmj4VwfGP3MGmkqYWOF2nP/l+At5WsMeEwyCua+0a/ihf17jIam
-hHjdahI1/JRkPXxHjaEK+yPelXCeK1W4vRrcyZbaY9mye0191XpfagwlYrs67i2u
-DVFImM833wOkGbU+H2qPM2rPdUEXMrXnKkV6G2al/UOcKnMN9jgNGdKqRO0+43DN
-/XwMQccVnMYyDYct7wp8HbMv1deY8b0nGTWG+bil/iQbhEPJsolERgd7wMo41/eA
-MPPYHtT7qvW+1CAasefK4R4QzgfMlOjtW3LY191a9lwlzBfjupX5WrewJ32UIRxn
-wMmVgdYJm1fXOaiMq9f2Xh6EQ5nYhMMdVeYjV3Hyt9SeZNQg7HCPCPCbThnR6Ajn
-U+uLvMtIOJTMn9bBQNgzA8Wt6v4ODxaKH38FzeIEq84+UlgLRCbeLulO10myXqLZ
-4CyCWbtqk66mmqZAQ9BpR1TgnePpd9BuunDc+RGAklRVytwQOAL4rtp+4yy8d5GX
-HVPHd5d3r6u94mDx4B1R4bPL2dXMqfZx1+vF8ZGu9evr61ltpIWTnEBQn13Kl3pt
-sHsnctfOiQFVRb1UawvCgshdH9sa+e51fRHvIm/l3n9w4ri9n6vM3Hq/2Xrme9Hb
-xfbIjinXr707pbYobuCtXO94R2l6Kc8ua7u99aJk/TFw1+39tJnrubXl9JZe5CyO
-ELaqu97lVbXT0lk47nFy5PxQ7ZZ4Oyf+uI69U+xxsOPTRRAfJX2lvpDZeht9CFZH
-GOxu5k7daW0V10vPj5yVc5TT0Iqtrch6xZwjXDOTdEmvjxUljn9knGv58ro+LYdt
-oyNd5Dvn6k6uoeYtjlL97LV2WesyXTjMsyJwfo90dC9ndRm1dFb++thGXV8qdTG1
-XW7mwerkaHev7+Tabs2caP7Bi4I0WM0XR/peXl9prlcfNtosjkmQ13eXU6/WCQPN
-QXz/ATu3951q2rVXE6ypF0Szd5HnHdkLTZp5V7UxvcUi2MSN5J97RNwVEn6PJH3X
-4DPWnc43qN2Kh/kguIfB7Iwx7xbe7g38rwvgxSgnu//wl8cWN27X5fjr0ncHuJan
-s4m806Pc3AVRnHTd+2Axe3zmTH+4WTgtMMCBfjMLwO8O1qubKFl8/jHebmDT4hfV
-pn/+58XFxW9/fvn4JTgLIO0f5U9Hvh+n6103Dliw8m94DKM7Xe/qPjVuKnepb6TO
-hcK9Zt68EubIH8ZJtvBu4vUimOWPImcWbOObC5n3XgarrnDDlYviCQf2Gv7MYx4X
-8tVV5C076LjXTbH1hhMs/1N89b1brxL+TTd38HES+SdS3mOf4bDdbLzIdWKPv5h5
-7jriH70wnuFuo3gd3WzWQf2TckVdv9nrnHzGlfete9SJH/zT+wStHu+CxeLG3UaR
-t0puAfhRoN/HG2d1HmRs+lj5tK7iyrUPEKw22+QM6NjusbqIrVB/OA9lbFaVOEgA
-3SDxlnFOBuE2ToK7rJuHisTjvThs/5Y0C2JnuvBmv53x6eiwbXNQOG/HA8PnfpOq
-9npcbxw3SLKbCz2ny9UaqH+xTr3ZGfM5d9tae5yD5dmDtPZ9fMrkfq8Pf0W4N/IW
-ThI8eG+S9eameyFdKsc44+YhiIPEm50ePG9ZMlfboTouoHAG0FrDg/f3oD7OgFNt
-d/D6bu1u4zPAYLvHqkTkfkqDKOUvzqDjc2fR2uMcWjx7kNa+j23a4vMZaQoNnbnP
-1a5q+PtzgB+jvWPdatR1rGl19Y61bKQR9BObaEQEVM7I82jb/JO5IWfuZW25ncXm
-3jlihDloFh5p4C6afeCDkdF42ThgB7QTQ3lLW1A7kFVtKB40bEH1GFm14VAjqVYU
-au3aMKiDaxm1ShGtg1abtY1ZA9YyZFVktg5ZbdY25JfI1RYEW/mlDdXWDi1Itw/Q
-gtBpodyK2umubUg+QQKU+PDzqdSABvnBA0ZHOFh8Fj0B+RjTtfapsUlru+qatTZr
-Ikce3GogR/7iJI6t5HI8++JM4V1b3CPZRE2d7+7e7OPxtW3jofBzINd3TpKks7rV
-Nu9Y0+rKHWvZuIU4laYtPHuOrbt4Mn/r3I08JPfW3J/jWyn4scaEGA4+e4QDZmzk
-4fbuzXzZ3r6RM9qbN20yn2HDJj9x6qf49URG1jO2u036VydYtpaKqBLGhfbu9Oen
-mh9nWgzHtfxxy65tEp9P2otnzf7zEy2p84yfE/bKF823LRsvCVZNYrsUYpTrIUa9
-GmLEmGTn6OmJQmwtncXi+GhKdazLpnDmhX7OYAsnavz4URpMrQ4mS5XR+Lz47Pdx
-0bMmerdtnGfpc0IeET4JauVE0To94vm0deSk0jx/joizTdafnwumGprmc9qvLIDe
-r6Ry1oa1jIThWxEpv+QB8DwH7bIKuC3ztPpx+ADN6oIU6Yj5FsGGd6R9HmE9kA7D
-gGwup8JVnMxqEPwwwo5PUo7Qa0lqjbGfnOeBbdPWruomtTbjaqTZD2rr9LXjy62p
-5oex4+NZ6c+KBp8evW6YPQGHAzXdKLi/eLPPQ/Bcmqhb3XW3+Ulz+IIQ8l++P8n1
-lW8y/Bvb2SesTqtFqSQ3ytKhxN/608Y8QzueMehr/SljnqEkT48pP2XEVh+/xbd8
-Jrhz2eM87/zLwVRkac2J/4LzeI/N4dQvgPjUhTsZnP4qkKqqqBrGPgW3/QN+83eF
-Z8N76tKd+PLzFeA8R4OfE9WppCB+DYhPXbqTwZivAqmyfDxx8vOPS28WOC/22TWX
-6sW1Cn4JJqTwYx7L9fTEWY9SQlIBcu/1aFVwCVgNyZdA1K7yQyt7qDMvnj8B5p++
-lQ75N5YOCTDNtgXss86aB82JuweJMm/2WOFvCyfxPr2QXuYQNpEXe9GDh43bAAar
-ey8Kkm9E9G+uPwMgV2CgTBuzocURsVflln5jUnhTy5Zs+qamkTd7/gG1f1d1kwL7
-Zu8gR1/EKiqRitwoL0C0GPs1GK8rQF4fQAExv12eAtNU5aQA0eIB1CBUZiMfTmd3
-FhjlohK/UfaBoT2g8yCVwRzA+E+m7WeWBTkP428lOP4AJTjOJKlvxTP+A4tnnCdi
-vtW6+A+vdXGeqP5WdOIPsoutLmxDWYMbqXNovZw2RI8272zyWHOy3tyIaMCbSoyk
-eoyCfzPfW3FowJ5TNQNj4Lr03Ru0cuGXBufs1xddXfruZad4MOEPDo97nIVFvhjV
-k1HFauYfEQs4q7VYjLaI/I30zQ38t7qB3+q1fKvX8q1ey7d6Ld/qtXyr1/KtXsu3
-ei3f6rV8q9fyrV7Lt3ot3+q1fKvX8q1ey7d6Lf/p9VqW65mzOGtfOKrrxXYJRg4S
-QTkbOU4iL3Hv9zCFq3308NMN/zzX9SNnFnir5AXI3o4qffcq8qfOC0XXX+X/pJcv
-X9VbNzR6hRBeS9+97EgdIN7mTrJ2/UrW1Vey/vrVhaK/7Eivmp8reiMuHeWy+TkM
-eRai+Yi1p6+171owea23vcExxXTP/RpfPuxZ+0YPYDpK5C1f1X7DeEjp13JPJ0kc
-937prZKbxdp1Fq/4/2M3Wi/yH5XxF8HmRsSnsNRPQZ15EJRT0b3nzJrsx1cHLaaR
-s5o1fYPYN71br5NGYxQI/Ebq7COwexJ2gua4+GFONesGq5m3u3kt7SEAm2yO978L
-dt4Mg9ESD0VLbw6Zby8dOAc2HQRoLqFUiPGHtMg5kEpCsZvdiN3Jo4V5onWbaDic
-ea20Ej/j5Oy65fH2IrlOpocHILm1XcKhLZ2bA1S1KsZtmRx588tq87a8bZHtJ1Vb
-74431+vNT7S/rLb/CuRefBkAiVA+hCVfXF69jrxlR8VTOMjYe7bD+OvCOyyIdRq5
-zr3yBPw690qBYv28zucnTLOYVj6lJ3TuBEv/4CNMQa9qTsG1zzIceLBYbM/Yp0oz
-/34dJ6e07Plne+o7XOWtM1H94S9PQ/aHvzzux8lzEJ823cNvcELgReJ0BEhBubT2
-/NygVByQlcrbhPSLn2Y4UNGocyHrccdzYq8brF4l6w1/oEvL4unn50xcjPqsmV8E
-cZdnZTesChf9+RTl1imVZ7Cf18GUhLAE87bxU0jnJD/vWetCrkgMuSYQhOj8GkMp
-VeG0H8PZbJ7BOKUDNSJP7kC1AGBvFiTNibYluaRxuQTtW/J8i2/ReVHBg69I55jF
-xde6jnJej7JHsTelkmS95LxRWAHwiGNT1dHVBsCLlffPoalzpid/fehHluL5RHvO
-XNSvDfvITKpjtRqzFcUol49eH3aebpOkkaRL+Q1IOOd37fAX5XlU+KHE27F3onAC
-5oDwL84drOLZKVX8EAvZUnygOd9DJN9GldP4uTGyP4934BJd1L/4NlXAqh5Oboqm
-KBfVnF38K/cb5GdxRMv0C00aVVKVBXjo5UybQk7ni2yxndrz2esI6kp5n+p2qOi4
-WidB82lVJBteOVSAKNURFWjmhu/PbWkbtajR+cN/f4YAKeU4IVd//ZNQ/4zWC+9v
-U2e18qLfKn8cdT1PumiNXuYf5dzVwTJrYolP++stpvjeVKrSVyugwxZ328Uidlsi
-uYVMOuKR798cBVX2xsvbXHHepd/FuitcT6Vm3X1dZaz8C5Wx8jR9ejqk0428By/i
-pSmepGnbSqE8TV2v1smLcsz4ZS6jxHz350u+ppyXL1RZrWvkBj5VS+LwjNhavb7Q
-1w6uFIuiVwMscpnKD4yurxc/OXBvfhf3r8q0HfnJfox8ru/zFPP967oi/0pHpMmI
-abZdripM8Vwcj41QYbtWrtOrHHciDotxsgYo1zUoJ+KzLWC0yxqY44HVFih6Hcru
-WWAuD8CcBedPFy4angun6Utx7gjo0ptjJlqbHt9/VcPPRLr0StdeXaqvLvSX5eza
-PNDbFGZS41f7lh1JRJfW2+TznyomZOfCXbNu7G3wSoZ9OFekM2NCL35TkTvS51rP
-6WIbRVm5aNBdsEi86AZevNA3u5e1Hv+cOYmDoZffHs/8ulUsn9TRpe9yAc3Ps7rO
-wn0hX252ne87F7q3bB/ubxju2UTru2Dh/faFZ1j+JUm/4ryKSPw1QzoeKsSeyEeT
-f98Nr825tCNsElNG/CHDpL2MGPMdYXN8RuxhOjDcdBDONWqbGrGH4tlEG4Rj6COR
-21TBBD57qBLbB7yqcPCgGVEGxkQy+wQT7Sibp5Yx2eEzTFI8hAHPrFtN5n3MmLLe
-1rJ9mYT+Ds/MVOC4DPrQIFVJhgmYOxL6MWU+4JhZt6lKM+jTiylDfLKB4Qp8hvkz
-NjBcOYeDyYc20fNnCOO2t6MGh4FzD/JnAMOFtZEGhqsBXP5sLp75sGcSyVKN3L4l
-mLwMz2D80I8to+djsrPh6qbB8bVu3zpm8FZylz9tXeXTg7uUrs0VT9ievvtJ+jTy
-E+hj3koKvZ1jwmL1oORx+nbXq5XnJt7M8B4C14v/6wmdhmZMQ8zKTTGzOoMNnmRA
-hJh9a/RTao99fBYOZWq7ChmlCm5wiNmhGTVcxgk53VFmYgYstU01J24KRGmPd8R2
-VUHcKgUGwQzroUJYTy+e8UxWjbK+yuEBwfgAU4eNJYifCwSlD8KxTGxfpwbg57JB
-OJaoYTJrBATVq+EChJXWcObERkNzS42hZhkmE0SpABFbI02m9pjRcL4rnt1qumXP
-gUAZh3ewfshoNBzGNJz4ttFXOSMDgbvAYArvB/PC9wrOO8j7+cggQ9ZXeLawmVnG
-WDDNBBhPw3mHpkYNt3jG5wECyuVZ0qwvkwz2yMescBL68sBwVZgHZ3zcZxX2mDJ3
-R0dcGNDQbYDh5kJDoRmugcBriPBoBvvoqsQu8ORM+9P61GmKHQ17/sCeSH8fmQ8f
-/PXVQKXKJ6b9/RSj3nuLzX87c2aWPUEpOGQkJbeaRGw/o0xIRtYDJlAG4XBnGaZq
-3fYYQelqYnskqkyTLSDA0IT26b4tMjDCB000ZKZORkVbrp1CXxsYQCBjDQiXBL3M
-MnwB39SQiIICJ5+E892+LTJggb84fqEODDcbhH5Kwv4OGTmca4OwnxHbT61RqpJA
-Y9QGITPRTMPU8dkItKavW/ZQKZ7dYl+da1xBwDYRqfyCOUBIZfkcXX684LZEqKEL
-7VkDDNB4qThSAhpWHE1IFS4QcsLHVPo9g4ZzntJvTPTiyIFgInyGRwkaYGTFfFRu
-VVRwUcoMyo9BgGXS3x/TKBivz1P/DXdXgwHPsv18hr4txi2OMFT3JT+qEVM23rcd
-FW3VPSyXvx/h+9OaOfSfrZkXa3+9Tf7bWZ6R0I0te76lYBiFYHS9JYSZ8iB0U8r6
-Kc3SHTF6W8p6KrF7qtknjID+Adls+9nA6KdkpKUW6GkgCWZKg3CiETbc4ckyPPU0
-V2lIdqZBMnqrZZZtapZNYmKDiMjHeWsQZrJBOE9JSBQ8oWL0inGgL8k0nRgm6EeO
-c+gzCnp8hCdGtiScZ5YB7DTXB6Gpk9DXCTN9G8bN9uPiaSTRlgQ4rlrCGchcjOPr
-MK51qzFYT8swY8seby27lxE20Swc1y/WZmAA+1TGZWSkqcRwd8Tg61wdl2SDsKdT
-NmFklOrWSFMsg0jEBmOX4Kkhsa5irUDnjjU8WM/6pXH7IK7zcUAcw7gFzsTu7fbj
-QN9evnba4f6RtJjDwd6njORrX6UXHeCIPRS/F6IKaEIrickdMXz+zOin1m2+/oXY
-yd+rDXDEMxxT5fs83FHDBAeKi31m7gZGf0cQLyKL3w38vYyDDSoKHKL+jozKY+TP
-sA//fS/G/UM4Pb8Y5xbx2onfYV5pZV7Y1kwPYYpnI9HnAKc6HMC9mGeDGHz/MOMi
-UAe1SOyJP7D76XPEYJysI8f/r3fAMxKCSvVBvYA9r1ioqoiwf3spNYbQBtQgvBc2
-6TCj4RBMB3HSrpdSu89t0pCfdCOsL4O6wtOxoYmnBmnoS+KZQUKTn6yDcdDxNDNa
-wB+D/+BjmxoeNm+noIPaB/y5/T9kZib8mpy+GMIsfJ8++A8cJp7w87m/gPgRDXC2
-8LQxPjNwDXK/B5+BL9NDH4QaQ2YZE8m6zZ+Bf2HyYESG85XApAP1nePHTTOQEdzk
-IYybPLDuaHIE2E/PTQiCPgaYdKYvbPnlVH2ffBi9FzS/u5+9G68HNsyxl9BwuDGD
-epGNU064/4eg7/2pcjO07LFu2Yv+l5wsJ+HQH9gk+/vIxCInJR6afxi9p5weTMmy
-iUyDFE99UuZnlu0yMDkJ87eEYTBGHRhAJ4RR1pdAFvO+JKNsyAjvq1BjrNOwlwl+
-AdtDwqASP8HMKBuqqA+qfSVyqzEa9mXCkJZ5X9A/hot9aTjRCRtnNOhxnMIh/K0M
-jGE6AH1r93XLIIK3NY2Gc50ak5if9p4A7Sqou0JoDzzRU+ltKqF7YPiM2mMwnflJ
-ambuCJjfBvjwE5mEvkJw3PnWsicaMYbZAP6Fkx01+jr3Y00xf1MlIYmpQbbUnkgU
-1mvE+xK7pxMbXIwhxkEIyHbm5uuo0HCoDoyhDPtB7Akr4N5qGQ3RVompAXbZBNwZ
-ieRrYROVhEOF9yU6DccStf1CPlHQC0EqUbAX2BjsBcGLmk7D4Y7YgO8Q1li1bFej
-fH9kxJFNUsL7pjQkKjWIBPtDbzXNMoYpxb6Ak5tRG2lCGmAcYajA+oI7Y9lDScQ2
-MsLI1jJcmRgTWENwrcCOksQpcUYyTaPGPCUM9t3dUjZMiT2WSNbLeCByrFr2UON9
-wU3spwTdLsIG4SQltqvjuADHNlOLxzEyfup4uCPhUOJ95zIJe1z3hmCjjVPK3IyM
-UpR1xWnv0AQ8BYz+lhrzjIL9a3CdQG41ndvIAqYN7hS4TWBjEd0C+hk14dMDGs6o
-Ae4Pn4sFdlqY9+3LxB6mFp+LSo0+uF6qGHNHwjEDuw/XyJ6Dbbzj8h2rNeyoPddw
-3Mr6E5C1WwI6g40lQS8KMcYKuOBg7wzC8Y4yP6Ujsed2T6V2fwf6xULemDDOzxV6
-2es9m4DurNAa6ivkyf7Osl1BL3MV3HKkYdAzjGiAV44TtcfAS0KHwZhzVdBTRo2+
-QphYx3C4tYx5Jui/xlfgpxDZMtyMZKlEwM4MQT8SWehLPHVPDMJ5PexLxJ4L+YR+
-ikIZnw8JNImGE6AXpeiL8qzPZQwbajBfCnQKfopNUmogr2eD0FRA7tDQFTpdgzVN
-LWOOss2yTZALPA7J56tbdo/B3pNbTaHhnFHb5OOCjGEk5TwLvtMkozaR+LjjLQ1d
-kJuMy8Ue8JEk5EilL8gjGg5lywb+zvvOdWIQ7VDOo68ItK1Zo7qOSGvzBZnjSjTs
-aSCPua2yXyvCXKAbwEFHng4JyFSVMCL6jiUSmqmFYQbYP/T7UpKljGYas+whjLvL
-956wsUoZ8CjhYQ3DV4gxF319ndgm2GEMwyqhzyyjz/J1hDGx6gcbbimbKJYxVtGP
-4PNlFugIGBf2wCA6YajXBC2bO8v2ed+wn4FMQt0UYhUMWcwH/GSVsDnIHdz7Mg8R
-BnwAMrSvUD4u57/QT+ktjqtT2wWZqyH/4bq7jNoC53CoW7ap8HHnW8r6smX7Oz7u
-cEftnkLDPsr6sszg1Sj6CgnHmdDFZXkDPmnGfcdeLm8yaoCN4GJfYvugz3ZIcyDH
-2Fyj4RjGzQAOyGwq7GgCNmo4Vvha9beWPVSpTXZcd5lbkBeUAe+S3SCcS5SNGfo+
-uTw3XPBRAacdtV2JGBM5l+eUAVzQmTiuhjSFtjT09SULaC5omA/IYsSxX18Lkusv
-woYK4XsPuiml4YTTHAN54zNijDOxv4yyORN6nOtMwHsk9s8YA6+Ld3OwzXdgK4F8
-pEAn9kThehGrfEjE7sl1uhE2wA51rDHJaW5n2UO9sAHCCfjHqugrEcAJ5aewLfg6
-SYPQVWjoyyLkCry8I4a743s7BptFJyD/M26zUJBb6IfW+QtkBMjHnoRzrfEmt/cI
-+MPSIV9jX5BxquBrhYa9HeBsFvYbfoPh8gL2wvBBPpLj9mpasw2xwolqGaZOGRF+
-CRGyQtDnLdg1LvBGTNhki7Za6G9BZlj7d7luBJmLMg18t4ExBJplJPRVbuPBnCcq
-scGXG7JBKGwL8buwb8De0Sj4RGAjYr8xjCeRUfFO0EsxHsqvAcjmsKdQ1s94P5Cd
-JAN7Kp9TeX7I90BrgSaXKq34prGvOop+8ZE1E7RX2OJoxzKiEnvIClucmSCjMt53
-IlF7rpRor2zjp8QAGzK3gcp9QV8RBXxZHmLGvinIJJod6EFuExvw96SuQ7lPH/oK
-8BPYvZz/Qc+Dn5rTJvgArsT1M5Esg8jUBh5GvclI2EcbiOv9cWYZk0zQpo7yGW2v
-us3A50/CRntD8Np8Z9lzbj8ZYNv2Gec1WIuJQg1hH4H8DknJVwIbgigWt4EY5RWS
-cj+rkA3CtgJ+l7kdi3IFdHfuH4Cvo3EfnMsksC0BX9RzoQv+jMT3h/v/4M/xvj2w
-uyTChsLO9zWUYZnAiZkyp4nhloS+RI2JsDHHOjWGWe6fcfkLMvXAfjUK2W33GOw7
-t317O2oPmZDdKgUb3/CxrwX+lt3LaO4fhL0dZXNh4/tg42u5H0UyLaVGP8OEAehr
-jzNimBrnJaw+pnJZJ2x7XtEpw89Xhl/oM8sGH2+Iz7junMu5LW7Z4x0xTJ2M6rqx
-AZ+SXhVz0WAuRV97DH638HVcidjgH7u5fwB2n4a+WQY2PtB1XxbxlJItUF1/lF0l
-O0L4kykFGywQss/uq5YBegj3XCbgr6EOAxnYY+DT4rgVeklrtk+F1oRN5SvE7utU
-0ItluzI1xrlNpaLeYe6hj4u2KYH2UoN/nKEvapuC/mt8xW1EjTKTCTmsUAPsr3Hd
-vgReV4g9BF0ofIuybQpyYqhQ8G3Rz8W+KM/I6CCOADjtCOtJnNcrMQhSs6dBtukk
-BLmQ+2hlWxzk0UQBfUfC3BYHnHrIszxuYsqEDdVG/6ASc6n0rcdrsK9lg+/tH8p5
-9NGAtn29riPs2nxrOtuorVVd3+M3H/RbmOhrDzMS9oR/MNzyam49xu0IolMct5/v
-PQMbGSsVMvw8KlnGJLVGvdw3BBsK9CNWQ7SwChup+5Vgq6k0nGjUdrNiDwqftG5T
-CVoO+7rF+yrENkEmcR8N5cZYzGeIPpll9zPhJ5d5qGYHkpz/FMtAu0kC2UJR5oKs
-MXHdKSOywFkBn4uEWLWRVye0x7pl9Pm4Rl8mxkQhPO5blhkg24CHMmqb+3hEIW8I
-+qz4ncrI5Y0pEazyyG1xC/SO3c/9A2bZvkLtvvAPxirSOpfnO+Qbe4JrBTYOBXnC
-+pmQsSAvVG7X1v0DlOcp2NeNvgXqggnAy/0SoKksjxVZxlAjYAsdzgd0DOII9Fhd
-izTXXwzkRN2XQlsMY18kpbYp9peoFvgxWS/XmRnQt9g/idquTISdZ9kTRux+xukR
-8AF/b8LjcZmmW/YQY481uhE2QB90LNg0gub6OjXmWWEPwfvQzX1DZtkkLfwDkKeG
-2+DrAi/3U8pQLgs/eY6+r7BZFPCbCPpKNf7i8VCVgB18yJsiltrfEWN4yNfYF2Sc
-K/h6ohCjz/b+ga9Yxpz77mgDTFLwu07Z+HbNNuQVEF2NhPM8YTHjvjfY+rnvm9vU
-wlY2cvu+Zm9zv0DiqRW5P9AvbHDBC4U/sbfvTfF7bt/kPgO3EU0jt+/r/sS4NB73
-B3DuwscQ9lDhTxT+y35+pOwP/BJgPpRvGunDpyd+I3Q2m/gP9gHly8vyUvyo2vjx
-pOkjjfiggkSJH7Zo2It5koCpEBDYaHTje3T6OYGawjHF59q+n5/3k0jRb5jt+/ml
-fkMp70eNYdGPBzTwvZb3g/e83yTb4zkp8EThguPhe44nKlez3E/b9/PzfgJPDOxn
-+35+qV+O56TAE/pxPCdZgSca3AWeWoEnM3M8VbLHU9vj6Zfx1Ao8mZnjqZI9ntoe
-T7+Mp1bgyQPdRT+Bp7bH0xd4Pp+x3IWznWX/oaxFMCfnOazVWsWa/aNPw75CR3kV
-6742COcpRfuqHxPb3RJ7qIAPzfNJwadyFcLmKRmlO5qB7nVVGvZkYHvQE9TuyxbY
-D7a/xdzSkQZ+nGoZY21gAHxMugcbDvwneF60BflL7KFEmKsMjL6K8DB+PfaJDT6h
-m9KQ6FjNOtNSy8ZvhzomlAegG4epZffZgOOiWcY8tew574t5QH0Nq05DW7BdmM9M
-o58NQEcwd4d2D6b1jcHfkPicTbA9dRr2Uxw30HbgrxHU9dB3zPBvG+YBNgVh1BiC
-770TsQ6NIFzMY1Ipflvr7/BwAfM1tC/gneHv8FvhqLcjsGboNwF5w1x6GmFgw5o+
-sfvgT2rENndYfRtTKn2J2r6K64A+x1yihqvzvq5i2T2J4MGG/pYavkbZUOfri6mZ
-jK9vfwv6ifs58M7UaUhSEs4Fvlg1WLIMgnRBwVayTX4oAWOrQ0ZgX7Gvq6B9KvAl
-xlyn9lC3OM3oFvhaxkQT+GYU7MzQlzh9mDvw6XOcqD0BO1OCuaItwXzwryXTAJxc
-nRp9btsDDdm8ujnmedj9rWUAHj0QFzsRP5Qte7LjfedAfxp+B4G+Rk+yjKHCLyXR
-UhLCXMHWhfmA/QK2/wQPjKDtzno7nlPnby2jp+MhDaD3W6ysrYt8IR3oHfaXMpfj
-fpvurJHGMJ87A99/qFL0a/K2YB/6KbcVYD38jBpDHb8hYx4Y0Gqf7z34amwINi3y
-AFZlZ5jiK/r2MvSxMI98voU55HlmuB4MaA4Pkeho89l+ivjh9wn8FpDD1SysTo94
-wh4B3+o89tTbEvAfbZfREd8jYs8zyiZgE6WDkMglni3vfUZugd/7Co+z1+gm7Ak+
-nDPK+8K6yiTsSxyuCXZrihXMMddwAv5gji/4sEBHDXQ+h70AX00iXBaoFGQeVs/u
-8+r6zM+IkAUYrzDGGpcFGMsBuLLom1oGAZ8p432H4CsqhSwo8bQ10oBedoSNAScZ
-5Swb40Ef61bT8TsOxufxHSO4rxOkB8r6CmEE8ztr8kfDWFRoZpSRBtkFfScyMXwp
-l3v4nQLpAejW3PFvtSAnMG9Dw8rl8A59rCETch5kI6hg1fxp7dsA13AZgffgT4ST
-LbV7MgEfHvyYTNP493of9AT44DIxxhkNYZ16MQlBHvspMYhMs14qeEzFb90Y2+vF
-nGeITA3ik1tNozb4DSQleDMA+KJA5wTjhegT4vdg5JlsEOLhJGbZmCq/xf20e4yA
-XW738HsNZUPoy3MLDV/DXFhjjnEG0GeUjX2kuXCI36pIluqDcLzDw1oh8hv4STox
-yI7nQIBP5csYtwhNn+eTueBvaXSUyoPQT/EwmTHXTWOexztVzNm41STMWwM+F7KL
-2kOJssmOBmnG4xsm0Cgeyhpw2QS6NwZ5hd9AmSsRw98N8Bs/0EU/pXZfQ7oAvxP5
-spdSvD3P3FrGBPw/icfeQFb2QD5pNEvBxwb6Sok95t/ZMqBd9G/1gQH7AmNj/M3n
-MaGxQmwXfGEV4zr2WAObwTRMnn/C5jtqzGNrpEmWMU4RFvq7/paGPYna4P/C+voq
-NYhKDLyhAvaSoX41fNUCmgXTkdsgGjWGmsglrtMT+IsgqySCtoCpYD6JbSqoP0Oy
-xd9tPCdTpc1+qg3CoYp5CHj8otr3KablxRZPi3b9aJ021EOAxzdy3Rx1osDpTrdx
-9rck2nq/HRafPNHhxrlL8N5pXrXj//2/N4eFgcrV56TGuj1y6cLOr3wZ6ps/0AV3
-H8f/xy64e7O/YvTwLlG8TKpGfpto7UdeHP/zwVkAuTqbjedEzgoLZ6+8ppo6eGlC
-fnKaF7mSN7u80FWtPIuy2b2p3rR/dPybm/zurvxFd+pE5QLM1fFLwzwZML6ogOYY
-1kDLZ4Berlk7wmdCxRPqK+ehy++GKldFvQAerlX4K1UMvLh6re8LBoo7phqAc9dY
-eMz8j+5i7cyClS9kj7h06lDilK6hKp3gLx/sFzUj9qUxS0vAKak6/30ln5sLZV8t
-jV/tUDTm1R7277ESekvh4CeS/pGCyIpcriqrwuKDwI/vo2A1r5c7bqgpzhG8d2br
-lF8x1pE6XeAR2MycT3D/7pxlsMhuBk6yfhU7q7gbe1FwV64GGXnLpr2cOlFeT+aM
-Uj2lTWsDVpSOroLL16B0sZi0L1CAJVMUnVdbwfqMTbW2WkbEamTV0Yq6DA0VMvd1
-ta5ybhAFZfQG7qhWzzyGAZbWrRbA1PT2Red94o2zqnVSTndKovXKf6yXEG7pM01W
-j6UCf6VCFUeL+h1R9UXRcFGsrlr/rxWPbeR70RMmyx9cbFfL9XaVeLO8jpd0vEOV
-EhoF6NFy4d9VaLVaMeegLjHepdCdeknqeY21yfnCcnFTv46hxN1SR9vs8J/UwSIm
-0iv470JWXr6ClT58I12+LFcy4Th35Lj0sDvzYB3k+PiCiQpZr85pdHMPkziv6UMQ
-B4k365zVmBcJPq/t3drdxnmlzNICl65mLBfzLheejA5kcLmEdIuMXDkPLeJlz1eL
-IE66cZItvG6SbYTRc57NDrQUrRfxb3sTPrfeD1UL1jCSlXKV7gtV1yuSjOvxc8fK
-/YtKcUupZR0OwJRK1DQUm+Ey/ftOuepMo2SRvWUHu+jSd50u2IEv28yazXrDkeBc
-JNCv7M/+2tLYdRbeC+llqZB2iWkulLhTtC0qTF/IcScvDJQXmW7HpaXeKp+/hLMR
-024UO3ttVFwWIGg1h/Bw3+l2sKZk+eoCZ5usWwtVlg2kq83u0Mau1UmSlZdVYQRt
-1L3IKbW8BnkEuylftbyvF/Qu7YP8cv+ou44CoN8r6bvOkU1xt9PA7U49FnjRiwvl
-1cVr/dWF+kq+kPWXb7rLuChnypkP+e7Ibu3Nd373A9jY5ZqZR7rmMn//EJZ+U9Kt
-RQ3CJwPhxdPWdyg7HmuFKTtSB9b6qt3SPwKYFzZshiyggjV5BHJ9vpXa2Yd+2/mQ
-yhXj8uuAa70d/ufSW21Bq/5WUzxcH9TaPB41R+oQGxXaQSPUOOcM3giuuaXQYnUW
-RobS5FeycvlK0eRXF/LLGkerB4RQA90SCioqTXpLrkZabK9Z5KRe4RWcCZxX72vV
-n3zH665pUW8R/c69KFSkA0D1LelwYAtn6i0eWxhvFjzUF321Tl6UdNbLx7oq59pL
-blsbUIHFLJzNJgbzOn5KVf5SSX5+KyO/QWzmueuIe50lL/cMO71yJ3z0FKy7SydY
-VVFvqfXbMKOyjby3RF5XyoK2+e7HJG0bnu2G57FOnMdO+yd1GN2Vs/T2kZMLLaq5
-hi3+VgsusbfZX5XQUlD9f2ZX8F/uh7QK+yb49+ulJ8otHli7VX+LFwM/G/LF/3a7
-7jYCQvt5vfRaiUgMwus0flXwOLVaGf1T8EEdIoh8TcCw50Ukhcd6YIUoYIUcU68I
-r1HjnhM2OWbWdbodZbN7eSK0chqPup4ufVuouDxy3YxsGw43AZi+tE0HcrgehciD
-ATPvztkuki+CfZTnzwRR17JHrbwCZF3p1WIKjZZ8XXbyNU+cKGmSnyfCDeLyioP7
-W5qVxXqbgBpomlttIjhVnCYwFsaG/kizOdypqoF7sG9NF1vxyzWOCMIS9LJdfh7w
-coHsJ9NZQwyxAc7pPW2IVnT5R76q6VFn3mb9/9ThgSGX62mw8H7A+GbVtGoKo+2p
-66lj4YoJ8iupPrnlNqJTqiP2kiRY+fHhKpapfurEHpDom/KNM4cfUpC69z7wFsxp
-14m92ibUrk/5F5uD5Rlzgft45Fvd6c8RJwPm7aO3eES/3+ioUHMUHo+bF3tUGxVE
-+0eg+of1k+HnQmpe8fuLvGUHfxUhtaaIWok6mu7HbAq4IRy96baTMjmVbkMC7m26
-EPmr6qdzSmDV5oDLggv0/dG4oQD1+MQ7RnHauQTL3eY3lev4T4zYhTV58mfYBqBZ
-BerUiXINhCjlNwcq+BUNxjjt3J93I07tAtXyAp4eoiFWKyRd13vwVkncquePwLlz
-FvEhoDZjtgoo/zhd+hRdZdDmgG7TRUGV79YHYktwRGPkuSg8r+xLzXcumr/UnFyH
-fEalyvInhjoj7OPEwazpC37xfb6yHNeVi25VqaSJ6yTTwnPNsey99sTfFk7i/fqi
-i/c+HzpxLXHMpoldpEFy392v0mNpwfbB56ctWcPOiFVsnIX08gtAnom/GrcH0M8Z
-v7NdPJ75sesMYKB776PmSxOeEVWuQS/ELiiOuhF9VBjyWIH4qi13Wm6JTtZb9x4v
-M12vbjbOqpud/L53MMhZjvtpZjk5zHbRWQT7y70b7qE+A0TF+fn+/vSHkkr/ox50
-bVbROt1bPSrYO8X/ZPh/Qy5Yyc08f9HRcts7DEqzk1C/avd8+K6TeP46ysrXFJXc
-YNDM8K+sro9JrL1pWrtQx1s9vIidO6/rRJ7TRWNYvKrxNDenBDhx/wlXwt/zds5m
-swhcNNUOrsc7Tiw876veRyCo768wbF4/kTWGrCp0Bq7K3qU+2PVypldLSmGe4PGs
-xNINHnt695P+6df3d2Rk+t47OZ6uyLW5vJdmP/cuB9m1OlPd7YyR7VR9vxowMyVG
-D5MmzeCt4vzyD3W4vNY+jMx9wiczgw/hjs1+XsSfbG3rqsPUUz5tpu/Sy+nyevvp
-V+lqoFLJ+2W3+BDm5V9oPPmVsg+j92xm9PZlUoPejiz9hCokGYQTn9xKO/NWkwZ2
-3ye/ki297e0w4fMXX51kGk8+HUn4fGD/xAYjbJuQkbTz5lJGRz11ZPTlSSZtKSaW
-9v1BOEzIqLdzM01CWKPezjH66QSPwx6BF5gPe/xxftdmQN99nH9693E+2Ze8HvV2
-I2MRDkaIH4y1pSNpZxo/KcT+R0gCLYNx6K0Gc9mSoCcPQtMnkr+zfp7sBuEiJLe9
-LQ00aRC6W+tWk6YG2ZJMygYhNQn7KeRr09sNRoBzPyH/mGQT1oM1S/j8JMD/cjqS
-dNPoM+dWUnENAlyDog2sAa7tSNo5xqyAC2uOa/Mr7MMQ35vGT5dTmyR07O/oL/v9
-KdYI9gfb9RPyi78j7wiOB3A4DFhz3Icd308sC3RwqpWv56d3ZsDplb+X2K/sp7vi
-pKvdgz3KaKCpE9bzByHMyfXJSGMD2+T7F5KEjDQN9yBAHLckgDWEuWuwt4A77EUy
-CMfwbkszLcPn4djHPcj4XuHvt5oK+wVj4r6NcG4w5y3NYDxYe3cL9IPjwRihmwxC
-c0tGWgY/gQbNW021bV6CAPYM6AFws24laWAPE/ozSTj+PvyUJrjvJqw17Am2M42P
-jM9t6EMbx7gv0ZUEfeGn5GaSgIOwcb2LKymelM+utKTG8++aXyezQr0uJ2WjAKwF
-jprNf2exqNixhTMunZDL7dH3cqOmL+MHjXhy16szU4nXG2/lzYSvWJvyQUbJhfyy
-+Qb5+ryPJDJX8OXX27X4x0K9XV9UFFx+x/GhzuLGy/7jA88DPHBcME8I/yc15C51
-Cqdh8uLSW77Mrw2bReuNIKwXPEPw8jC1R3/5e+Q+icUSW3VsAQ9TgMrTkVo27/wc
-oCdiXMWunmXHN7kUGIiKxG2+xcUddFLNYcH4E/daKkm05fRzHq6q5p9j5+7F5TEr
-6cgE+Cv+7LE1of7AyypR5+fG6+2cyL0vxZcOffinfR4qf4qs2vlXhbH/ui3t+zwv
-q8C562yTdbz1fS9OSsnoh/HZ0nIVklN7qgQ5MezF/3a7KCG9WRGdkZ8B50jMKlhh
-yL9yaAvoqUIDh2EcEb3hka2ShPqvLhzCCN5A9cTCIXgrx1Alockre/HbLXa8ygy/
-aQTMH8sepnhpElYJnEvE8PktA3hrRV+jYT8TFdYUy5jsSDhRTeg70naWQTTK5jE1
-JnjrCrHNHd6sglWB5syysUqagje2hD2V38KBVUPF36kEppclKq0OGeLEsPKS3ccq
-dvC7ZfgaxRtMCN5CYtljUSG7rxE2lwmYoowwPPFv9DSsahjkc3N1vIWE9fKqOQTX
-hldgE+uDpzC1AVYqGuIJUpJpeCrZsk280YVmmkzYRCVYZRnGM0WhFMLE6U2FhHNe
-lMQgGRZawRtViEoMXxbPmJXf8sGrgGk0NHVxo0dW/I0VtXqMiEIqQ0Yyaw8r5i4a
-yQ5hEFFMhYiKwPMttYlCWY/fPIMVx82MXyCFle7FfMUNL4abkRCrPWf8lDTJRCEW
-sT4mVqfgFax7Yk3x9LxObKLjDTTFHGGNgYZcnRi+QsTNN3nbAVZ+R/iM3uY3+eRt
-4Rm051WN8+sicQ2DYg1Flc8cJ2hfvlpymAn4Er/x5Oob73zjnW+88wW88+H2elW5
-AbEDKrvDzaVO4Wg+0+LgTdCKEucwywkYPLT2TI3/7dT173nq+oAADiINsrcsRQHi
-TbDqHB5SPZ9sgtVmmzyen5Gg76PZnJiUvctbJK7mD/iBDPR33lQOazV5SNwj0Ta7
-r2OB48TydJby2Ee+Jx2DxFNTynkM1Sk1H0o/BXbvG3w9wOJnsF7FTe5P5Zu2+C5U
-pIepm8q2l76DeMsX8mtps9ufQRInkJ66982n+2HfD8IkX+9E0qkPV09YSR7zeKxk
-DDwBZOIk2zP3RXho+TF48b2oW/Wbq8lC4sPSf8euPW+jFkGcHP9k/QVUAEA600rK
-83S9mBXHfEXVgecAfzzcyMou1QJOz9i706cgTuF4eGCrio30HKAYKTr5dfhJ8abn
-ocGzBipffg+OEVc+FrelV54cKj84UA6LNSTW1Y+LY2pd8dBbLIJNHMRvnpcucBLJ
-eDvlhRVOprqdBHUf+PcLWDJv1lyBpZbXqYmkTqnzdO3HJy5qQlTslnKCnbf8zIFs
-N5t1lHSX65mz6Bw+KraqRAjndH5SlFbRCmbnsuk81PIIe0l/y3hQ6fOPWEdm7mV3
-kbP0YqxZ8ngXrZelaHy0TpzEeyHNPP/l52R9+EbVr/Hd5x/zE7NfD+D668H6WoAu
-tt2HIN46i0XG2e1VUXyA/32oqkvlBvLjq6VHfJ8vpEs18pal53nK5sGLGruX3hRa
-rAz+QF6UXrqLYHMDMuCFGOZVy8+XtU7djZPccy58oUvflV7DAt0HM6+SBPQGU0qC
-RZBkAmtoxs92VqsI5Y+73dSJViXX9FREuyE95zDb/+Kqfqjuv7wAtmX4/gBvip23
-V/SVJjKZD7OPt3lFX7xEPiVhX8HbIGyTV7i0JzK/DXcu81s4fB1vD8fbtV2VhGMZ
-L68PNIli5U8T+mqD0NWojTccwDvdMnwJYyVVuISwHhuE44wYQ3lg9CWs8oo3Frw1
-sLIe3l4zlLAqKN7IwSu3mgZJSaYpxCYyFrS2h0zcVsHjewbeDMOojTdpSyTjt9kR
-G29Y0rACqkFUrI5qEH6zEOvjLWWW4W8Jm+vE7mX1viT01UE4lyzDZVgpE3HqS5aN
-F/tr1q0G73Z4Q5093A1CU6HGPL8of0sMc0fDuT4w+vzmBzZWqD0XRaznsqiem2G1
-UryhvYQX9u8xirf39iV+U7WfkqyH76gxVCne9NEXtzblOM+VKtxeDe5kS+2xbNm9
-pr5qvS81hhKx8UZkneLaEIWE+XzzPUCaUevzofY4o/ZcF3QhU3uuUqS3YVbaP8Sp
-Mtdgj9OQIa1K1O4zDtfcz8cQdFzBCW9danlX4Iu3DNTWmPG9Jxk1hvm4pf4kG4RD
-ybKJREYHe8DKONf3oLiptHkP6n3Vel+KN6LMlcM9IJwPmCnxm0vqffFmKZUwX4zr
-VubLq5H2UYZwnAEnV8Zb//FWhtI6B5Vx9dre89uzbcLhjirzkas4+VtqTzJeWfdg
-jfltuIxo/GaEel/kXUbCoVS6Le1qoLjN0TP+46/CyS4F0x68KAlcZyEOtKA9zR0Y
-VP/OIpjlaku6mmqaAo9BXxXK7M7x9Dt4Ol047rxoLElVRYnKed/prvp24yy8d5GX
-PVaON1XbxMHiwSuUKPfgqi3c9XpRhsLt8xqUhZNUhuInzmqA7p3IXTsVYPzoQrUd
-CyJwkXKk5bvX9YndRd7Kvf/gxHHeylVmbr3VbD3zvejtYlusEDfya6i7gbdyvXIz
-7lzX1nLrRcn6Y+Cu81bazPXc2hS9pRc5i2JzVd31Lq+qTZbOwnHL28YpoNoo8XZO
-/HEde1WCOFjP6SKIS9uv1CeXrbfRh2BVENDdzJ2609rM1kvPj5yVU6IktKVqeK9X
-zCnoZCbpkl6HEyWOv3fj5MvrOjoO20ZFA/nOubqTa4N4i9LOz15rl7UG04XDPCty
-VvuB7tzLWZ0vls7KX+8X5vpSqbPGdrmZB6sapLvXd3JtdWZONP/gRUEarOZ7H/Xy
-+kpzvTrIaLPYU/bru8upV2uCvmkQ33/ApnnLqaZdezW2TL0gmr2LPK9YDU2aeVc1
-eLlr/thYURc8v2d7+7iKwexghL3zD8AEzFrjH/7y2GJi5wcD9NLBhxyPMqqbyKvD
-FOeveVDoLJx/KIeRqj3ABXlTCvwki88/Cqc3flFt+ud/Xlxc/Pbnl4/n4yO6fP78
-49KbBc6L/by1K2/58vFkQctSLUA8Yycdr0hZLi15rM4huFXdeHlOHaqTbU5nNPIZ
-l8uTKd7y5ZtadYr8eck/jIoq0BhqaKqioUvfdfS2ShrHMvDODtBXW35BGCaPvbw+
-OxTUEG+5uIq8ZQM9qdIRejp3uw/qfe6D2bWD5a6zCRJnETBvj0tRS0m7upAugfxa
-EeKFOV+dPixawfhw1pfqxbWKjvjLx4t7JxZVGzuHJ006F+vuwsnW26SrbJyVF+fR
-ALErl9GpqqBl5qp9NNznCZeLYB5b5Up1ycf9hF637e5XmOLr01MULfGLTWm66mbX
-gJR89RWQqpJzQUKXWgv1iDNAIo1VeWYSa97/Eo/ptdCVmB4PQmF5iQo5lhRwE/7V
-zokzXXjJ+f2RhdQqjJkXz1sh/OlPf/3L/3Ti9TZyPeJsNsHKH38c/A2PcE+d6GIZ
-rC7cOL5YOpu//PX/DwAA//+ywDEqTR0BAA==
+H4sIAAAAAAAC/+y9a5PbuNEo/D2/Qu9zait2djThdWyPK6nIQ8ZLRwDNFXU2ck4+
+cCgOh6RupcuQhMv//a1ugBRJkZJmPJuzmzN5ah+PQKDRALob3Y1G42/9NLhNom0/
+CfK7tTcPNr3NKlr0+/17b3Pf7996m+BK6+v93tc/9Hp36+Uc/+j1inbbtbfY3C3X
+8+veern1tsEraRqEr99jpeJ/Ryp9+0Ovt12eBKrq784BW6n27Q/f/vC3/8pRXfr9
+223LYP7lrSOvf7vb5H/ZrnfBv3t/7W1W3uL62rvbBuuLst06CHczb/10AJvAXy6m
+3jp/OoiptwiDdX+5286iRfAdqOxut7Nfof0zDvVUF2IqfjX491F4P4vC++1ju0Dy
+9ZeLbbDYXvf++Eegv2m0Wc28/LoXLXDhbmdLP4EPD8F6G/nerO/NonBx3ZtH0+ks
+gC9zbx1Gi/4suNte96RLfR3MofjW85Nwvdwtpv3VchNto+XiuucHi22wbnxeB6vA
+2173FkvxZ+P7JmLBdc9fPkDL3wJ7PIkmcbbTaLq9v+7JYo7uA1i34vcL579w/n+Q
+84tty1tEc4+zZ8cmKm96sJbeuhct7qJFtA2qO9rT2n/7LS3U901kRVRFcy8Mrnu7
+9ezV/0y9rXeNBX/ePIQ/ZvPZew714vNPVPmSf9Buf8l2PpMW3k8/S76xfBiqU3Wa
+6yrJ9Qd/7j+QeJCSm3dsOvcX1k9fVl/+Ob25VcN3n9ggJDcDRiL4zw+nyiyZfoRy
+M/+Uf1h++WW28H5yit9z75ds83k0zb8o1pK4jjI0TIXcpBll4eoT0976H/8ueTcf
+HvyPf4+9f/6sfx75OxKPF9ZH590nScpoNEgnrqlYBvyHfaf4L7NC4k74f0XZjcTI
+XEot4+d74sJ3S3wz4d+c3gwyEuF/vP5okA5dS/qUv/3x808f7qcfw/CLIS1c7O/D
+fR2+Kfr7shy6TfiDLXGtLXE/XSEsPm8/3oR/+cv/vP6/KFx/VySieh9n0peRXy7F
+rfrhfqLMpMCVFsPYkj/lH5LPoynFZfhoAmkgeezJguScTGqksiXs05bcDKSJa8L3
+XHzL8N/YCQ9JRcrpjf/wOc7SyT9/Xh4hxazoz7uRmvDToWvm8F8QAaz0wVe/LD6H
+ywZJ/Ioi5r+HOPyYxIn65ZdJ/olp/7BuBr8ZuXETDcLnlB03nYTyays336c5/L6o
+6ed4nP9sfDL/H6SmXf8h2uy82Sy/j6bToMtxsbebvNvNcrbbBr3/L5qvluutt+BG
+0nI9DdbXPalRLswM6VK6UtfBvPG1sDo6PoOddTdbptc9jlzj88qbTqNF2NLpfbQN
++puV5wdgy6Vrb9Wo4c+i1XVvHfjbV0XfF71jf71uAChUVgDUX3kwxmixCbavdOmH
+Zt3if6fr4oLcR9OgYxlKm3ixXKDm+xBtottoFm3zYo4AyN/mwTTyeq/mXtYXC3Cl
+Xr5T3+JAAFDZzXx529FXo7fGmL5Vu4kWZTfaYRdb73YWbJ+zF+1tuSq1nqbBJnly
+P5e7frBeL9cdAPzlbLm+7v2vO12ZKtP3tQapt15Ei/Cw5fVtcLdcB49ybwgnxrrg
+jMKL0WGwS5dv3xw6Oh4raqMzRG1k/TRdffnp5+XnkZXRyAq9j/979UW5l4rf0/ls
+NpU+PQSGFAnRxEVkzMXql1LkftrdKvrMivjv4T8/ybcfx++s+f9WvvyiP3z56ETW
+Tz/nk1909mX+Lr91pWj606f72wXdTP758+wfN1JuG2EI2pR9k0Sfw2Vo3VRE5Xy2
+uTWkyJImMkmc/OcbC8Rn5LqWTkdaSmJTsd1kQ1xLH8Y+o+5EtkcfDBIn8jAeK9QI
+dfsmzUgc7ijzVRKPZcuwdBppEnUHme1a0FYbxr5G3Ykivum2EUoktppwCWEDNozH
+OTEceWiYEhlpOY0dneYfDMIG0jAeKIQ5EonSjBrWjsQWI8yXLIOkJNcU4hKZxpMN
+cR02hPUwSEZHA0YMa0fdAaOuqSHcXEuJMWDEHYeuYWn2SJOJQVSSA1yyI8YgJcyU
+LZPA/O0IS3TiDvJmWxKH6jBOJNvwmT0qcDIl253oFsC90eBbRpkDOGXD2FKokaiW
+mea2O94Rw8ponOhDw8ztkaYSNlaom4S/RB8on2PAY5JTMPwMs44Xth8wGlsS4nWj
+SdQIU5IP8Bs1HBXWR3yr4JwodbiDBtzJjrpj2XYHbW3VZltqOBJxfR3XFueGKCQu
+xlusAdKM2hwPdcc5dRNd0IVM3USlSG9OXlk/xKk21miPk8OQViXqmozDtfbjMQQd
+13AayzR2Or6V+HqWKTXnmPG1Jzk1nKLfSnuSD2NHsl0ikdHBGrAqzs01IMw6tgbN
+tmqzLTWIRtxEOVwDwvmAWRK9+UAO2/o7201UwkLRr18br30Da2KiDOE4A06+DLRO
+WFKf56jWr95Ye3kYOzJxCYc7qo1HruMU7qg7yalB2OEaEeA3nTKi0RGOp9EWeZeR
+2JGsvy+joVBTh4rfUOmEV1v882fYcrxoUXdnN93n2yDb9m+X2+1yXmiE3iyantgG
+pbe3mqaIBrD/ndo277xAvxP1b2een5zqQJIOVSOu2J3q6e6w4cqbBR/XQX5yc7+7
+untz2HwTzR6CU5rB9Gr6duodNvaXy9kZfb/T3717N23pe+Ztz8Fdn17JV3pL9/fe
+2l9656CgKuqV2jJ7LFr7y5MrLN+9aZv6u3Ww8O8/e5vNCQC+MvXbAEyX0zBYf5jt
+Tq288u5NcKe0zKAfBQs/OAOCdHslT69ayGcXrLfLnyN/eQKANvUDv2URgnmw9man
+mErV/eDq7WHruTfz/DNInzPlYfttkHmbn5eb4CwmbSWh21m0Oc14Stv058vd+nO0
+OMXwd1P/1r9tmfvlPAjX3sI7zfmomrdM33LBvFPMO5V0SW/rfb31wlM9v5Ov3rUN
+3WO79am28p339k5uwTqYnea56RvtqqXt7cxjgb32Ficxv/Ovpm2Sdu4twuXJBX93
+pbQJ2918lUSL8/q/e3Mnt6z61Fsnn4N1lEaLZHYKyNW7t5oftCGyXs1OSr03d1e3
+QUtrPIaJNvefEcoJILea9i5o2TnSIFpPP66D4NRSatI0eNuCRTCbRatNJ/OVZmRp
+PxZ2oiT90OELaXOtQBlqAvsPRc8FRUTTc3EpnCO3y6xm6vbnm/7dLMia5VCGThXx
+vQ9YVrGF/7V8OAOvv/b+VMft0NwufSQ6n7G2qanN4modnNn39V203mz7/n00myIa
+3zPFf+1dz7xj0PxZtOLzug587q1bb2foENrsVkBWm96rRps//uvy8vLffywdKY8e
+0QEWAuKpEKIzTrNqZ8O3y6y/iRj6+7izsSCv4n/dNQ4IsyCCFvoUn9rItPJp76i5
+7kk96VIpXTC844bbs/Jls81nwXVvs5xF00rx2ptGuw20kEtY82jRL9w8ymW1VIB/
+I4r2jtBL+e3bdTAvvUQHyv5yVXK6KNoHwtwtF1sR4lL1KuGgy/iQsnkleGy3WgVr
+39sE5cdp4C/X4ii+8FX6u/UGRN1qGbWE3tSVuPd1vaIyUc163RTW2zyE51DZ5iHk
+wXnRbHYNWK6DxfYGujkFvfcjnnmc2wmvjX01IpVUMdlHuosWq932nJ6wIt9amhN+
+BPxfzx7JX/ej+H6BX2HuA3LEgMZiR2j9ijEf8KEfbYP5pvq5Cnnl+Ukn4LaP8L94
+t9lGd3m/dNvuq9R22COn+dNo493Ogum/zzm5b6ncfuRWVOTHbmcHBdSb4fItV56P
+JwfSpV5l0MUShMNsmQbT88Z3NnF2NzkL6bO76Wxc44tzx/kfiMrYn6+tg5m3jR64
+KF2urnt92ESUE+Lh+iHaRNtgegY2RdWm7XYUvOcDTudAb9Y8qHAPqsI5kBoVD77f
+Lf3d5hxAWJGfSNf3EG7ud2xExcdzGODsQXU3OYeGz++ms3HzYL57Oz0SidYFhPsv
+Tu/dRb2zOjuHXo81bxLksbqN+T1WtZuohGe0naj2btMzAv46ieVklOBjlv5wNbzZ
+6t47prJ7aF4cq+HPut1NhzigLrnyQPE6TT2Nte9A9lAidiF9WLMD+XMosQubJhV2
+ItOs2IXLAcCOjhuU09lvo15Xt01wHb02ZHNnr416Xb0+lwTvQLeb0boQ727RMYQj
+XXTgdIb878TujLZdeD5WfNRY9yA87eytowirOMn8+/CLEz2dw62dbZvc1VmxMaud
+9TopmDueOyi4+Hga4276Oh7A95iN4nDuj0SrdgLhy1o55mtZZX6UdmZPrQuNcM9r
+3lzrY3Ubc3usaveKi8G1r/hjRt696CfDiB+17q1M0xl5eubK7zm+yeJ4EPSYHttZ
+vUtSdIPp4PruBu2s1l2/kyaKMbdP3KMn5KQ0OBE2/B3U0bUntYy6ofVVvJiF67Hu
+ofj2eO3pXHXnuIJyntZ6ZHDfztOLHzU73x6tIp6p052hhD3LVHRFnG+jRdd+UvWI
+y20ecb3FI47+9JMXG0vJOfdmszO6Vw47v+p0xx+uWVf3M2/deWZa7V497F6WDvvn
+Qy9nquLhP3c+7nad09E4aSzPQ84Bu/DW62V6zILsasnprnuGBFbebrs8B5Fj4Bpn
+M+VAK+vAu6nNuXLuWnd1XRxIlIdIV+WR0D7q9+qgm66bHC0xMl2jOJi/SmB/dYll
+JOr6uNuOmwAH2GeawclNe//wZKjjLAqLU4H17XI2PXEcdXp2DtW/rooNW7Wz3n63
+7DZEO9fq5XSl43Sl81Zby8HJ8Rtw338SchqXA338ERi1qludu+j30/WZqJ5N/63m
+WIuf5tFDesZzlD/1fuydJTcbB7XFcf75d8bP1GakhvhtEa41kag/GpFzFZvHYvJG
+fyQi56o4j0NEfiQWRx1URzweTwR7Njue50l6BjiH29Sht+k7shW0BLY+E+RHT+XJ
+Y5znAdWy7x+c9pyCfzwWqvuw7slwHz2ZJ45ZnwPQ9yhQ53om61H3zwT50ZN50n/4
+PKAOJ5RfFoBh/+ElL9vvMC9bhPcxjozo/3pKnaj7xkhboF3rHOGfM28bfHkl1aao
+u07Z82odbIL1Q4DwjyISLe6DdbR9YYbfb5JCGM0CtJzb1js+4hr2Ra1q2HofqrVq
+x7Wz1rrrYPo898B/U2nuyuG1mzPV8ZVeq0OfVcVSKAF2mCWtEN8cgnzTBnMeTKPd
+/CygR/LfleA6DJY2aAeDllsHnZ0PUrk8cP4pNRfjHugjoDZBtsH7HfDSbyBx3Hlz
+8JKd7XeVne1Man1JqPabTqh2niR7SXz2u0l8dv7G8JJ67He1nsevk7ZnSOIX79oU
+l7O17xNIrKonAHiGIIkkWu9bPEjNi3JlxMpeLUUN/uwMa+XJhbiXyvV98eOYtfzP
+V33MLFYWTHjBKQv6WLu2G4Pnja46+4e3lfdrWTmwL2EulmL2jx3OiIiDF9v992i7
+v+QffMk/+JJ/8CX/4Ev+wZf8gy/5B1/yD77kH3zJP/iSf/Al/+BL/sGX/IMv+Qdf
+8g++5B98yT/4kn/wJf/gk/MPnvZF/Wu9nAV/ufUWi2D979oP0cHe+XgXZcGUEwQ/
+D+B/i0gc/qNB/8euQj8mu+Gx/IYiCmq+nHqzX403Kpgu1xF6kgpVvvm9QgCL5XrO
+K9TuBQmCWc5280WDz0pe66jTcqtps10HW/++61pT4/PBvabye2UWhbfs5O32/YSG
+a28K0/KKx4lcIFUAmYi/uIlzwQVuf7Ndrl6p0g8XSAyvL3rb5at1eOu9UnT9ovhP
+ev369cWjO7hbL+etsGp9vyn7ft2TkFovvmco0kUPu5S1dxeyrl7I+psL6VLRG70q
++g9nVrwqKh4M4vlmqgX/o1Om/XBOraNDLJA//FYsQ9ORysewHxMamEg57ag067fU
+4gvfeyP9sF/71mYHWPY617m3X9p6Z72upcSOz0O41748vf2KHOJzZB14z63zfTI2
+spmephk1CSDxcvjFwZ/cl1770QDhbbeefz9H4Tpb+t7sovhn46+Xs/LfJk54miSO
+owrJvt8RKyerXLjdB960zZ1wcVjldu0tpm3RFpW6d8vlNjgnfy8I5XKf3MtpPMkv
+LxxX94Dql9Nb+Tk1agLei7qjD9pvErJ+tJgCXm+k2ozC5rQ6A1apQOzVh4ry8Bvb
+pCs1+C58sEW31vjPXDt+ai7ovXr2kNYCdaW69t3PryvMVh71FrcuWyhNqxxvnkcX
+py9Sn3GV+uhl6grm+9jkDrVYbRzRnjuGlrwtZyik7fx1kA27zPHhZf3mUlVwbxHk
+HWmHuI+xxrxHr8YWk6N1L7yqH07aUZgl1ELm1eerK3y9hs/VEXzeteBzFOgJhI7d
+2C2IXzrCGFct+ByDeQKd7Ax89CP46G34ZN+D0DkYXR3B6KoVo8ej9L1S6bDG3W42
+2/hH/EfNK9mPQKO7+3O6bUqDNsu7IU0OVu45FKF6JBoolc00PPLl1ds362COm0dP
+KlMH7TU0DKMRl3takv6fgXHvXnkU0vdKM4KuNbnKozaK7tlsqXR8PsswFG6qVXeC
+2sTKfGIVPrHVLe4MvHDOHoWamLV64oH9BZ1W2jo+0P1YCgJ5/zgg0TzsDK3cb5lq
+ZSNtCbjknUWz2e4clqjVC++Xm+1/wun0+8lg0yYMDnSVc+e999fenx4794XTudJp
+5ZLr49exPTa5YrisKxk70LKRm9TGM5FJ9aR+TSotBGMtylT0LFr1ZF2ab3qBtwn6
+0eICehNF1XLE4+mNv33HfBdjeeqEX0abPk8j0LEYe8uxnEj5vEnrGvxZk3ay8aFC
+vQEAbWGJZ4jmumws5Lxal/OP2p2eCamavXNV335arR+uxD3bXCgNZeKRBukzodOm
+3Sh17aY2C95q9fvbI9o3+VZDEsYXTKNtd6qBqm5V+FvKpkeSJezvk1QehmoN0T37
+9KISt66c3bJ59rf3NnIFTak/c8WLOYot5ny9FuwkB5UexdzHB1wbcoeSePbAD4cu
+d/g9zhY4Zy+XfLjUz9DLqaX9lcXtY9aubeV+hRlomYPvk+1nr/CBBfAMfZxa319t
+C3nEyiqtK/v8Y+8WXLWVPXqkUbfZ5HqS3RYgt7vttlO+Vy/WobR8HAj+oTnKxgbx
+iMU9C+fuXbt7327ZuU+fV3SeWKyDh2C9CVrc5AdHEv2Dut3HF9W63x41LfxD3TO3
+d0TV3CxPAXy9WG5fVWNfXne5SdqdEZvgjLTs4oqruAqHL1Q2HiQQzHYkh/mRa6z7
+bXJ9kMG7Oj91f+LhAetly32jroeEDhMLdwasKZeHeVaKkvLYT36sXnJkqgpT7vKt
+rJa+rXU1Dc3TFYoj3dbs83U9682vs7+fMwfq4Rx0HScBPO+2NSLyUbZUIR61FqXq
+/I3n1EwrTapXjmlT37nfnp5puW2mOxRYAW6x3EbdCXKL9XvTGGbjUVMxlMLl/dOx
+y76HAZCPQerHc/WP6sX+QgWCfqD7mdcVtVuKAp0LqzOP9punFZ3nltc8ZkWXLnTt
+4kq9kC71182btpXjgmNeH+lS3VxUGvYk4a5Z7rZdzp7jbb794Q/1AMlLf8n6m2CF
+e+9XIcal9+I2Nt4SPggAkd+XgR9yT3pf/PGtDvlfU2/roWH876+H4Tn76Jy2rGcS
+htIWbI6r4Hsz/5V8tcqAPvRg/rqzu7+gMb5aL++iWVDrm2cS2a1nr35b91pFzhBx
+t9WK6dhRiDuRj95v/ei8sxIpI2yyoYyEDsN7aTkxkoywBMuI66RDw0+HcaJR19KI
+64iyiTaMx9BGIjepgnfUXEclbgh41eFgAiCiDI2JZJkE75JRlqS2McmwDO/hHcKA
+MvtGk3kba0PZYGe7oUziMMO8JTU4PoM2NEpVkuMdw4zE4YayEHDM7ZtUpTm0GWwo
+Q3zyoeELfJyijA0NXy7g4P06l+hFGcK4GWTU4DBw7FFRBjB8mBtpaPgawOVliSgL
+Yc0kkqcauflA8H4ulEH/cbixjUGI93kNX7cMjq9988Gzog+SP//7zle+PPhz6Z21
+4HeSbz/+XfoyCrfQxrqRFHqT4J28aiqrU/TtLxeLwN8GUyN4iPxg819P6DS2NjTG
+i6cpXh7OYYEnORAhXjA1zJS64xDLYkemrq+QUargAsd4ATKnhs84IacZZRZe8qSu
+pRbETYEo3XFGXF8VxK1SYBC8ROwohA30soxf1tQoM1UODwgmBJg6LCxB/HwgKH0Y
+j2Xihjo1AD+fDeOxRA2L2SMgqEEDFyCstIEzJzYaWztqOJptWEwQpQJEbI80mbpj
+RuMkK8tuNN12EyBQxuEdzB8yGo2dDY0noWuYKmdkIHAfGEzh7WBc+F3BcUdFuxAZ
+xGGmwi/EWrltjAXTTIDxNBx3bGnU8MsyPg4QUD6/CMxMmeSwRiFefCZxKA8NX4Vx
+cMbHdVZhjSnzMzriwoDGfgsMvxAaCs1xDgReDsKjOayjrxK3xJMz7d+XpxIGZDQe
+hEN3Iv1jZD18DpdvhypVvjDtH6cY9T6Yrf7bmTO33QlKQYeRlNxoEnHDnDIhGdkA
+mEAZxk5mG5Zq3wwYQelqYX0kqlyTbSDA2IL66b4uMjDCh53IYZZORmVdvjvFoTY0
+gEDGGhAuiQa5bYQCvqUhEUUlTiGJk2xfFxmwxF9kGFCHhp8P4zAlsZkhI8eJNozN
+nLhhao9SlUQaoy4ImYlmGZaOZSPYNUPddh2lLLvBtjrfcQUBu0TcVhfMAUIqL8bo
+8xv0NxVCjX2oz1pgwI6XiqwJsMOK2/epwgVCQfh4W3zPoHHCb60bE728VS+YCMvw
+tnwLjLwcj8q1ihouSpVB+U1/0EzMfSaCkvFMfrvd8LMGDCjL9+NxQlf0W97Sr69L
+kY1gQ9l4X3dU1lX3sHz+fYTfT+/McfjknXm2DJe77X87yzMS+xvbTXYUFKMYlK4P
+hDBLHsZ+SpmZ0jzNiDHYUTZQiTtQLZMwAvsPyGY3zIeGmZKRltqwTwNJMEsaxhON
+MCfD5CmY2CNRaUwyyyA5vdFy27U02yUb4oKIKPr5YBBmsWGcpCQmCiZhMAZlP9CW
+5JpODAv2R45zHDIK+/gIkyLsSJzktgHslOjD2NJJHOqEWaEL/eb7fjHhhqhLIuxX
+reAMZC76CXXo177RGMynbVgb2x3vbHeQEzbRbOw3LOdmaAD71PplZKSpxPAzYvB5
+rvdL8mE80CmbMDJKdXukKbZBJOKCskswMYaYVzFXsOeONUxuyMxKvyaI66IfEMfQ
+b4kzcQfZvh9oOyjmTjtcP5KWYzhY+5SRYu7r9KIDHLGG4u9SVAFNaBUxmREj5GWG
+mdo3xfyXYqf4rrbAEWXYp8rX2cmoYYEBxcU+s7KhYWYE8SKy+NvAv6s4uLBFgUFk
+ZmRU7aMowzb8770YDw/hDMKynxvEKxN/w7jS2riwrpUewhRlI9HmAKcmHMC9HGeL
+GPz0MOUiUIdtkbiTcOia6VPE4Ga7XHvhf70BnpMYttQQthfQ5xUbtyoi9N9BSg0H
+6sA2CN+FTurkNHZAdRDJZAYpdU2uk8Y8mQthpgzbFSaAii1MjEPjUBJlBoktnjwG
++kHD08ppCX8M9kOIdRp4uLyeggaqCfhz/d9hVi7smoK+GMIsbR8T7AcOE5PYhNxe
+QPyIBjjbmFALywycg8LuwTKwZQZog1DDYbYxkeybogzsC4s7I3IcrwQqHWzfBX5c
+NQMZwVUewrjKA/OOKkeE7fRChSBoY4BKZ4VCl5/fqp+2n0efBM1n99OP4+XQhTEO
+tjR2VlZUT3R62ggPfxf0vU+cZsW2O9Ztd2Z+T/I0Ejvh0CX5P0YWJpqt8FDyefSJ
+cnqwJNslMo1STGxEWZjbrs9A5SQs3BGGzhh1aACdEEaZKYEs5m1JTpnDCG+rUGOs
+03iQC34B3UNCpxJP0sUoc1TcD+ptJXKjMRqbMmFIy7wt7D+Gj21pPNEJG+c0GnCc
+Ygd+K0PDSYew37qmbhtE8Lam0TjRqTHZ8IRmE6BdBfeuGOoDTwxUepNKaB4YIaPu
+GFRnniyMWRkB9dsAG34ikzhUCPab7Gx3ohHDyYfwXzzJqGHq3I61xPgtlcRkQw2y
+o+5EojBfI96WuAOduGBiOOgHISDbmV/Mo0JjRx0ajgzrQdwJK+HeaDmNUVfZUAP0
+sgmYMxIp5sIlKokdhbclOo3HEnXDUj5R2BeiVKKgL7Ax6AuCFzWdxk5GXMDXgTlW
+bdfXKF8fGXFkk5TwtimNiUoNIsH60BtNsw0npdgWcPJz6iJNSEP0IzgKzC+YM7br
+SMK3kRNGdrbhy8SYwByCaQV6lCQSoTGSaxo1kpQwWHd/R5mTEncskXyQc0fkWLVd
+R+NtwUw0U4JmF2HDeJIS19exX4DjWqnN/Rg5T6zlZCR2JN42kUk84HtvDDraOKXM
+z8koRVlXJjSLLcBTwDB31EhyCvqvwfcEcqPpXEcWMF0wp8BsAh2L6DbQz6gNnwHQ
+cE4NMH/4WGzQ0+KirSkT10ltPhaVGiaYXqroMyPxmIHeh3PkJqAbZ1y+Y0LCjLqJ
+hv3W5p+ArN0R2DPYWBL0ohBjrIAJDvrOMB5nlIUpHYk1dwcqdc0M9hcbeWPCOD/X
+6GW/77kE9s4areF+hTxpZrbrC3pJVDDLkYZhn2FEA7wKnKg7Bl4Sexj0maiCnnJq
+mAphYh5jZ2cbSS7ov8FXYKcQ2Tb8nOSpREDPjGF/JLLYLzGxHDEI5/XYlIibCPmE
+dopCGR8PiTSJxhOgF6Vsi/LM5DKGORqMlwKdgp3ikpQayOv5MLYUkDs09sWersGc
+praRoGyzXQvkAvdD8vHqtjtgsPbkRlNonDDqWrxfkDGMpJxnwXaa5NQlEu93vKOx
+D3KTcbk4AD6ShByptQV5RGNHtl3g76JtohODaIdyHm1FoG3NHjX3iLQxXpA5vkTj
+gQbymOsq+7kizAe6ARx05OmYgExVCSOi7VgisZXa6GaA9UO7LyV5ymiuMdt1oN+s
+WHvCxiplwKOEuzWMUCFGItqGOnEt0MMYulXikNmGyYp5hD4xsSVzdpRNFNsYq2hH
+8PEyG/YI6BfWwCA6YbivCVq2MtsNedvYzEEm4d4UY6JHWYwH7GSVsATkDq59lYcI
+Az4AGWoqlPfL+S8OU3qD/erU9UHmash/OO8+o67AOXZ027UU3m+yo8yUbTfMeL9O
+Rt2BQmMTZX1VZvCEi6ZC4nEu9uKqvAGbNOe246CQNzk1QEfwsS1xQ9jPMqQ5kGMs
+0Wg8hn5zgAMymwo9moCOGo8VPlfmznYdlbok43uXtQN5QRnwLsmGcSJRNmZo+xTy
+3PDBRgWcMur6EjEmciHPKQO4sGdivxrSFOrS0DaUbKC5qGU8IIsRR7M5F6TYvwhz
+FMLXHvamlMYTTnMM5E3IiDHOxfoyyhIm9nG+ZwLeI7F+xhh4XXxLQDfPQFcC+UiB
+TtyJwvdFTGQpEXcgN+lG6AAZ7rHGpKC5zHYdvdQB4gnYx6poKxHACeWn0C34PEnD
+2FdoHMrC5Qq8nBHDz/jajkFn0QnI/5zrLBTkFtqhTf4CGQHycSDhWBu8yfU9Avaw
+dMjX2BZknCr4WqHxIAOcrVJ/wzMYLi9gLYwQ5CM5rq+mDd0Qk3iqtmHplBFhlxAh
+KwR93oBe4wNvbAib7FBXi8MdyAx7/63YG0HmokwD221oOECzjMShynU8GPNEJS7Y
+cg4bxkK3EH8L/Qb0HY2CTQQ6IrYbQ38SGZXfBL2U/aH8GoJsjgcKZWbO24HsJDno
+U8WYquNDvgdaizS5kkw0tIz9azBoFx+ZM0F7pS6OeiwjKnEdVurizAIZlfO2E4m6
+iVKhvaqOnxIDdMhCB6q2hf2KKGDLchcztk1BJtH8YB/kOrEBvyfNPZTb9HGoAD+B
+3sv5H/Z5sFML2gQbwJf4/kwk2yAydYGHcd9kJDZRB+L7/ji3jUkuaFNH+Yy6V1Nn
+4OMncau+IXgtyWw34fqTAbqtyTivwVxMFGoI/Qjkd0wqthLoEESxuQ7EKE8CXNhZ
+pWwQuhXwu8z1WJQrsHcX9gHYOhq3wblMAt0S8MV9LvbBnpH4+nD7H+w53nYAepdE
+mCP0/FBDGZYLnJglc5pwdiQOJWpMhI451qnh5IV9xuUvyNQD/dUoZbc7YLDuXPcd
+ZNR1mJDdKgUd3wixrQ32ljvIaWEfxIOMskTo+CHo+FphR5FcS6lh5hgwAG3dcU4M
+S+O8hAm2VS7rhG7PkxbneHxlhOV+Zrtg4zlYxvfORC50cdsdZ8SwdDJq7o0t+FT2
+VTEWDcZStnXHYHcLW8eXiAv2sV/YB6D3aWib5aDjA12bsvCnVHSB+vyj7KroEcKe
+TCnoYJGQfa6p2gbsQ7jmMgF7DfcwkIEDBjYt9lujl7Sh+9RoTehUoUJcU6eCXmzX
+l6kxLnQqFfcd5h/auKibEqgvtdjHOdqiriXov8FXXEfUKLOYkMMKNUD/Gjf1S+B1
+hbgO7IXCtqjqpiAnHIWCbYt2LrZFeUZGB34EwCkjbCBxXq/5IEhDnwbZppMY5EJh
+o1V1cZBHEwX2OxIXujjgNECe5X4TSybMUVvtg5rPpda26a/BtrYLtnd4KOfRRgPa
+DvXmHuE2xtvYs43GXDX3ezzzQbuFibauk5N4IOwDZ8cTlg8Y1yOITrFfs1h7Bjoy
+JuNneDwq2cYktUeDwjYEHQr2R0z4b2OicdK0K0FXU2k80ajr5+UalDZpU6cStByb
+us3bKsS1QCZxGw3lxliMx0GbzHbNXNjJVR5q6IGk4D/FNlBvkkC2UJS5IGssnHfK
+iCxwVsDmIjE+TMAT8Ltj3TZM3q9hysSYKIT7fasyA2Qb8FBOXWvvjyjlDUGbFc+p
+jELeWBLBhwy4Lm7DvuOahX3AbDdUqGsK+2CsIq1zeZ4h37gTnCvQcSjIE2bmQsaC
+vFC5Xtu0D1Cep6Bft9oWuBdMAF5hlwBN5YWvyDYcjYAudDge2GMQR6DH+lykxf7F
+QE40bSnUxdD3RVLqWmJ9iWqDHZMPij0zB/oW6ydR15eJ0PNsd8KIa+acHgEfsPcm
+3B+Xa7rtOuh7bNCN0AFM2GNBpxE0Z+rUSPJSH4LvsV/Yhsx2SVraByBPDb/F1gVe
+NlPKUC4LOzlB21foLArYTQRtpQZ/cX+oSkAPPuRN4Us1M2I4h3yNbUHG+YKvJwox
+TLa3D0LFNhJuu6MOMEnB7jql47sN3ZAn+fc1EidFwGLObW/Q9Qvbt9Cpha5sFPp9
+Q9/mdoHEQysKe8AsdXDBC6U9sdfvLfF3od8UNgPXES2j0O+b9sS40h+3B3DswsYQ
++lBpT5T2y358pGoP/BJhPFRoGenDl0eeEXqr1eZ3doDy/S/PUDxUbT08aTukEQcq
+SJR4sEXjwYYHCVgKAYGNSjd+R6OfE6glDFMs1/btwqKdRMp2Tr5vF1baOVLRjhpO
+2Y47NPC7VrSD77zdJN/jOSnxROGC/eF3jidurla1nbZvFxbtBJ7o2M/37cJKuwLP
+SYkntON4TvIST1S4Szy1Ek9mFXiqZI+ntsczrOKplXgyq8BTJXs8tT2eYRVPrcST
+O7rLdgJPbY9nKPB8OmP5M283zX+jrEUwJucprNX5UBP73yaNTYWOioeaTG0YJylF
+/crcENffEddRwIbm8aRgU/kKYUlKRmlGc9h7fZXGAxnYHvYJ6pqyDfqDG+4wtnSk
+gR2n2sZYGxoAH4PuQYcD+wnKy7ogf4nrSIT5ytAwVYSH/utxSFywCf2UxkTHB5ty
+LbVdPDvUMaA8gr3RSW3XZEOOi2YbSWq7CW+LcUCmhg8rQV3QXVjILMPMh7BHMD9D
+vQfD+sZgb0h8zBbonjqNzRT7jbQM7DWCez20HTP87cI4QKcgjBoO2N6Z8HVoBOFi
+HJNK8WzNzPByAQs11C/gmxFmeFY4GmQE5gztJiBvGMtAIwx0WCskrgn2pEZcK8MH
+pjCkMpSoG6o4D2hzJBI1fJ239RXbHUgELzaYO2qEGmWOzucXQzMZn19zB/sTt3Pg
+m6XTmKQkTgS++DCOZBsE6YKCruRa/FIC+lYdRmBdsa2voH4q8CVGolPX0W1OM7oN
+tpYx0QS+OQU9Mw4lTh9WBjZ9gRN1J6BnSjBW1CVYCPa1ZBmAk69Tw+S6PdCQyx/w
+wjgP19zZBuAxAHGRCf+hbLuTjLdNgP40PAeBtsZAsg1H4Q/DaimJYayg68J4QH8B
+3X+CF0ZQd2eDjMfUhTvbGOh4SQPo/QYfj9JFvJAO9A7rS5nPcb9JM3ukMYznzsH2
+d1SKdk1RF/TDMOW6AsxHmFPD0fEMGePAgFZNvvZgqzEHdFrkAXx4jGGIr2g7yNHG
+wjjyZAdjKOLMcD4Y0BxeItFR53PDFPHD8wk8CyjgajY+wIZ4whoB3+rc9zTYEbAf
+XZ/REV8j4iY5ZRPQidJhTOQKz1bXPic3wO+mwv3sDbqJB4IPE0Z5W5hXmcSmxOFa
+oLem+EgXxhpOwB4s8AUbFuiohc4TWAuw1STCZYFKQebhA1Emf0COhTkRsgD9FcZY
+47IAfTkAVxZtU9sgYDPlvK0DtqJSyoIKT9sjDeglI2wMOMkoZ9kYL/rYN5qO5zjo
+n8dvjOC6TpAeKDMVwgjGdzbkj4a+qNjKKSMtsgvaTmRihFIh9/CcAukB6NbK+Fkt
+yAmM29DwcS74hjaWw4ScB9kIW7Bq/X0ZugDX8BmB72BPxJMddQcyARse7Jhc0/h5
+fQj7BNjgMjHGOY1hngYbEoM8DlNiEJnmg1TwmIpn3ejbG2w4zxCZGiQkN5pGXbAb
+SErw8TuwRYHOCfoL0SbE82DkmXwY4+UkZrsYKr/D9XQHjIBe7g7wvIYyB9ry2EIj
+1DAW1kjQzwD7GWXjEGkudvCsiuSpPozHGV7WipHfwE7SiUEyHgMBNlUoo98itkIe
+T+aDvaXRUSoP4zDFy2RGoltGUvg7VYzZuNEkjFsDPheyi7qORNkko1Gac/+GBTSK
+l7KGXDbB3rsBeYVnoMyXiBFmQzzjB7owU+qaGtIF2J3Il4OUurDe1s42JmD/Sdz3
+BrJyAPJJo3kKNjbQV0rcMT9ny4F20b7VhwasC/SN/reQ+4TGCnF9sIVV9Ou4Yw10
+BsuwePwJSzJqJBt7pEm2MU4RFtq74Y7GA4m6YP/C/IYqNYhKDHyEEdaS4f5qhKoN
+NAuqI9dBNGo4moglbtIT2IsgqySCuoClYDyJaym4f8Zkh3+7eE+mTptmqg1jR8U4
+BLx+UW/7GNXycsfzMoTrZfq1uHxfzRpRllXyRRRlmCniyAVSceXzIbiW35e9XMvf
+Op6C/nq3Xs6/Hr5hXHvyuL3423bZ3bB41Ljrw7dvf/utINLQ+7115PVvd5v8L9v1
+Lvj31/IKbZGU+USDa+9uG6y/FkkQ/+d/3pcQyvwP/EK49H67XF1L5dLy9Av8GrQc
+zN+LC9LwZ9uVXpGV68ybwJgpwl8+1Fs8wYRZnGHCLKyfvqy+/HN6c6uG7z4xfJOf
+Yah85IdTZZZMP4bFu//LL7/MFt5PTvFbmC5+TOJE/Xk8yT+xWkjxg//x77H3z5/1
+zyN/R+LxwvrovPskSRmNBunEFV4GfOtfvOGPqmb1jX74JjEyl1LLaL7Rb8K/Oaqu
+qO6J+qNBOnQtCd/tjyrmkiEtXOzzw329D1P0+WU5dJt9DLbEtbbE/XSF8KrhsSVr
+e4to7uE6yxvxHkQvWtxFi2gbIMO8P1mjQair9TJcB5vNvx68GRB22dNqFXhrb+EH
+4nb6fMkOCpu/D/KMiIcai3vuPFWKvMrKdCn1zMPKKnsvGvI3Ao8je13Kx+JD/9Zb
+V4zxRv+Vbh4NGD/UQHMMG6DlM0DDTHYifCZUzCew8B76/GnrMqNAT+pdgmioptHT
+JOn9PkXf5ds3ejB/X66PMlWmbcC5a0N4PPiP/mzpTaNFKEQafzP766EgK6TcH/9Y
+yC1J+qEUXPC3SMMjlTKvMgWckurj522Qhi6Vfc4d/gxkWRlhVb7jY2DvWx5DqLx0
+0F76q/Hb4cbxvkiUocjvKzmt1WC+370XQYh1r3kWiP7mfh0tksom8WQ9gSfUKh52
+amSALIqraR/LqtVZvfemy/Qa38rvSb0+MDhQ4p7JT9dBAr3z5tEsvx562+XFxlts
++ptgHd1ViFdeB/M2Yr311kUq9u/XnUSCrTK/VntqLZGbsiWflnjho710zxBd4ygf
+XHnaSAr6WQfzKvcVyaIkTNHJ07ACiT2eObrwxjwzT8O5zIdySJpCn2lQpiitEqYo
+Ahbiw35biEFOOZd6i1gUUpCnKD06sF40D7/W0sVdano3MfI2m5W3aDRSTjfarpeL
+8GsV1TeS1NXmdrv4Wq5tLZ/MwWZczfl1RHU8MCOkfR4a4FiRl6n5W6QQExnEOtHd
+rcNg/Yg54QWXu8V8uVtsg+lXQd/S8QZPo8OWjfgpu8fhpofcWGHBdYP1MHm6yJT+
+vp5SvSht5lHHNy77t8E2DYLFMzAOpxG+ZZaJpUReqRZhL/W0VYb/STwRk3QB/3cp
+K68vgCoOv0hXr99/N4CWNE58invy5n1r4WGL/jSAFa81KMuOk5VIP3hxTqXre5jG
+86o+RJtoG0x7Z1XmWc/Pq3u39Hebr4I2K0tceb62onRgis/q36c1kH1ONlnq2JwX
+3kNvN9snvdqLq1m02fY323wW9Lf5ihsRHRD+ups9iae79GaR6PGkId9sICx74ML1
+crb599dnUsHArAb1scmwZXmVZcvCYipRoBzo+Jgyde/i2IF65HuboNj2+Ev0DcnN
+W00Df7n2hKJT6uNnbCz4aG+h6ncTRNd0cqb52mlIPrfaeVIBOIarYK7fAq4N1Pbu
+p8LzdGh3bJer60tZCeal+tW7VHW9hZDO7avwjdXSRkqPnNVqPruWzHRcef2xV01R
+16rNiJrYSpd+6PV78ip73YUM9NfQSvRu4l0tVxxrvj+KcX+XJNiz6cb3ZsErqeqc
+LIuKlyykto3wUtn0yjblExSX8qZMWli8QfGURkfmosUFAMTFF0zCuefrVFj7T1Gq
+9oo9KlaVJ0SKfh7ue/2etoaOKo8T4us9LTx6d9dwMrxdZYd+qnqOSVBO2pUhqKvu
+NZZKi3egzgCxym87vr9/PkgFfciddCUf0pX8+rA2GMEgE95KP/Sk9x3FJ2nQ391G
+fv82YFGwfnWpXFy+0S8u1Qv5UtZfv39aK2CkcnVRdTimNQB17p15/JnKW29vHZxo
+CmpLqa0cr8cziy/vUJH5WqcsEOKwZG+73XgCCE9c3Q5FQIAt4RiU8gfQ++pr7QGJ
+Qwfs+ZAqqdMF0KNT0segwyaMxXL7quG6fP00uVksS6fxeAyPPncWRYvwHPxKjQwa
+XePz6o2fXC6pV4/HpLXHyra0DeZf9+6MvQV5bHfqBtychWjBbYlOHeZoF00fdLkk
+qHzu5bUiPX5eet5v3I9XDlZ/yuCq3iTBmpdvngYJC2bebTD7WtkemxY8Gn2YGhvk
+JRJt5UEF4QLAkrJlMJtFq020qTrR9KMSrImi722DcLnOv1YgVKhYCeY9+A89c4UO
+2gR/O9ut1/nXYmO71MtlvItm22B9DRVe6avs9ftmQaeutw3mwnqeB4sd/Dzml28e
+xX6nR6gknLf8MQyYgLeFosp/N7XbjiTRT/PztOvK0K0u/XDctqtQDGjkbURVs1Ha
+TcnlbgtG4tG9F5fIa6zRxbHK3N/RXNXTTsnO3vYClDvl52CIbJY8mv51t3PnqQDR
+mHz8EM9ApL1dh/GKSqUmX8jK1YWiyReX8uuGnqweyIAG6I7YB678cz882p4d8m66
+9tKgPM45EzgCfNstQFtXpLeqCM8uAVSDMI0e2la1YrO+PvBzcetVPrZRtEmkyrEA
+cBFqAmfheBpOZePnkhnV6GjrzSL/URPYRc0F302DO2832z4G3S6QsGNePAecypKX
+m4r27dkgNz/cetOw7Yy8vqdw3lCQN4Q+oPEfp0IDlFVDF656b67Kg37u1+9yCD7H
+8C//T7+/XYahdzsLzhBKT4H6PSLr+PlUU8ickWOxsXni9o0b+Y9HHU0C1G9cuz1U
+M3DDbygZWFZVMbCgEHuFjC90gnf6u3fvpifmBYXUo6NZWoDmNahg8wtvUVXbxFgR
+3sfpnWjPxPwFEx6mh8Jd2it4D2kt0OW5jizqqLQ4HwVd94OHYLHddCpXR+DcebPN
+ISBvt12eBlTEAlUif+oCrt1DeDh9jTChA7NUKJZH/aCF4/JS2T/J0rusnw921XnS
+nBWjbzFSTnR5CqUz9CNvE03bNpgyxKo2xe+E61R4LKRKQOlTyfU/J5XavbiHnk78
+a+Ztg3++6sOwqi7Pw2+dvk+pzfPZ4X1rW5TLNNreVyjgawtRHHTeSR7n13xqjYvj
+XTyJNQR5Hl0jqWN9pNff0eUTJ1/ddLufpdfvn6vxr9vo4tG4nUHS33eC3wC28B56
+9+v2d7Ce4LFuQH/CqZ6AgA6sr8cjoGT+GFn9V+XAiZ8yYIvtcuff4yv1y8X1ylv0
+8/ctRWeFIFQRrB1L9LgLCbSaZ1Y2ir56s+jrqaCw/Vnfn7XX7zuK9xtPWf5n7fUZ
+GNQOV368P31+02jf5f0/7do/CbzpcfqdeK1VNDSPB8WfHOxTLOGqF0iwuNrluKn1
+PYvQaS4Ul/MaVP0753rED/3f+5OMmqJ66D+vuLnPmc1n9ZNXoW+C7TZahJuvjSec
+g8XDq413F/S9deD1Mc5EfGowIbd/BTjxiCK3M37k9bzVahb56NT9d9MuOh7hzG8S
+NNsIBGGAwhXSvsDiHgLKdUEJOCtFmKUgq667Ax2XVArHyn80iQMj9SQO+Ps/ksRB
++vLx5+TLx5+jlyQOL0kcXpI4vCRxeEni8JLE4SWJw0sSh5ckDo9O4vCoi/ZK40hv
+f4aEH543sFR9tsBSgHR4IZZfAK//bNwkOO4P92azTgflwbciaEQ6YRV0nzxWK3XG
+WlQr8RPyizOvRi9XwSKYisOY82arM0T3si1IFwo7wnsfP59HLnzX5gFPc7oOwITR
+9u6yZrYJ+085tMS402F/oF2/nn3gaUe3Ef6/Fjd89WN3CH2v9CZPXl0F87aQ+oMq
+jfCy6Xq5Ejz0il9KuzoMC9dfl9FnZ9f/jYXyixUXdHyMCrojy6tzKbXFmTcqHCXn
+82PCHzcvj4V0TODUJqZ50YYzSeVEdF1e7C+8ScVd1obPG8MIuOO7dme3muaARx1U
+8xyIxv3Lq2O+kyMD4J942dfOxA0HjvoKd7d1uwm8tX9fOYB/noNGvBu72XrrbeO+
+LC9r3pbllxZ59e8OoXx8oqWa45XHe/K/3jztDv55Zwbl1Pe93Xa52YVhsNlW8gsc
+xrxWI4jL4KhfY7M5gdrl/+n3cZMOpuWpuvwEOEfiEqIFXlWspVfCgKkqmR4eq4vT
+dB69UNnM/qtzKTOCj/I/MpcyPlQMdpPFHzvgD/5mPPE2f3yZ3miq7TopviOPD6ck
+YM/wh1fxIV9To7GZi0cnFNuYZCSeqBa0BdvaIGBnbKgxwYeoiWtl+Ng0JkpPwBZk
+Q8NR8BHreKDyh4nxISXxO5VoBDjwx6cchjgxTEbvmviwB/xtG6FG8VFngg8zgx3H
+H/YwNcISmcROSBhh6D8zBho+9BIVYwO7MWWEDYpE4gTnhj9KIeYHbRptiMnbHbTH
+SK6hjW+7Fj5yTXNNJmyiEnx4DvqzRO5owoQtpJA44XmaDZJj7ml8ZBpsq1AWZcwu
+Hj7mDyOA3aqLR47z8jc+MjBgROSWdhjJ7T0sLMPHsQ9gEJFfmohH0pIddYlC2YA/
+xo2PMFo5f1MfH/8U4xWPXht+TmJ8AC/nPgeSi9zUYn4s9PXyR/0GYk7RF6UTl+j4
+KHc5RphjoCFfJ0aoEPEYeFF3iI9hInxGb4rHzYu6UAb1+UNvlCUp0B7OYVTOoXj4
+qMAJ6pOyLo7BKPH38NHbF9554Z0X3nky73y+ebf4HC7fDlWqfGHaP173YMvucb2s
+V3penqhx8CqoaYnUZtUI/mY89kt+xN9MfsQDAjhwvVVzXe3dMJtVtOgd5m17f7LG
++QQWLVa77dfnujOm78MCOFEqey+LqF/eYhfXOtBEfF/LANNmVHIjTltl/zltH6em
+SPhRxe9IpNcxSPx6QPV6WX3Y7TklT4Hd2yHPB1j8Gy0XmzZzrBYjLbIdYAwb/FZX
+NdKo5EEI5q/kN9Iq26c/EMkPHksf7ck5gTY6vXe/xWQIp4LEHrE23C/2tRbT/giQ
+W2+7O3OlhX1ZZMoQ4T79ut+gfolUxAW90EH796ct/SzabI8HvH4HXQGQ3m0txd/t
+cjYts7CJxKZPAf71kDRq697wNT6BGk7fqT2F42EqiTo20lOA8huSzxV+eb9cRwz4
+9fEBmOtl+r6l6DfivHza1PI46qyWJ66ZN64WZ92V+utkV2LMX5/gY22J6GwGfXZE
+eP6mg3afNI2b3S3Px3ry8t1JUPdReD+DRQ2mbam1O7OcaSJ9mdTb31w9VeURCPI5
+Ellnawpy9XZgMP/GgexWq+V6258vp96sd1hU0l2Fqs9p/KgTFEUrpTHfPM5DrTh4
+qyiB8qXWwWDeaoXbS/9uub5Fom9x81dc3Gem82gBW5kp+W0HNqtgPd80hnHiKuDv
+Q4IXCbJrIrxaWM+Z3RTdT88kW7MH5dPT3rL6QqtBnVDkFipP9toMwd+ibn8QxM3V
+0N/brerHnjyWC4+nv/L+cnV3AssKLfQuN/dRMJu20ET9tm55/7pCI2olNyz+XSeY
+evKYwiTu/arHYnIjhF5uD6Ef5/hfXHOIla53DIVPvnw8ejz20XlnJZJM3XBHYpLa
+biielhzzd4zjJOVvqn8wqGspw9hUqTuQKJYNZIJPgvo7ysYKMXzEh9yk+N4sho4a
+SW6ZhNeLJztqWClhvkxH0NbcEXTHT/KhYeXDOFHwff6YhNS12DBOcsoGORmlOb4n
+bkzwPXkOb7IjriPbrinC8AcyxZDLBNrqw3iQE8PUqAgTJcxUKb6fP8Z3okmcyNR1
+eEhsPEltN5HJCMZI8mHs6DT2FXuUZiTXMuL6MjEGzOJzohNjnNsuD70ksZkRNtFJ
+PpAJA5z8nBiOPMQ39yc6MUyFxmHosDGz8S1vfPd4Q0eaRAwRmpsPZHyL3fV1Gg/U
+oeGE1HUwxJIYPh4bwJipkeD88TBgqDPOh3EoEZcwG0MynZQyotqGBbjK2AeGhVsb
+yt8y12k8YTaOc6xyF32S4ThvtJwYA43GExna2iMttV0ztw0enkr4e+UMccWw7Ylq
+G7BupjKMrYyyhBEMJx8rNNIk27AkfhVgsrPxzfGxhG1FeKNtWBo1zJREoowNdoSH
+F+uc1vycv7/syxRD3mF9x9BOvLvtSIgn4B0nOr1BGiXUHWvD2GLESPhzqXhcgPVS
+Ghfv+A92tptotjuWaF60Mfkb5eLde9sNdeo6Ks577ACt5ZQ54t37RLeNRKaGH1J3
+ovN3jAeabcAaTYqyFGiSxIOMxj7Oiz1Kc3qjpcSdqCR2MssYK/RGy6hhqdQIN8RN
+dsQdKMS1mD0acJ50/Yy6ic7D6c2UxmZOWAL8KcZkAY012hbra2mE4fWHWlvqjpVh
+PJGoMcEwavtGkygLMUxdfAO+k0WotGIbIdAtp0EMyU5yasD68CsLeJXDhbkYZ8N4
+wigD+vT3NAx1RinOpXibWyNxkvE6eJyXEXfAkA5Hmmq7Y4XEFsgSRm80nTJf4vzm
+70Ae2QaG8cqEOTs8XjQShcsAR6Gxk9sGjJFI+I65G4qrCAOdYKg48A1hw3isEuYz
+muP1hQzkFHUTjmMM8sxhhPli7iyJuqZE4gmXSxgGbAK/yyS2RJlYbwZrkMB65yTH
+d7tT2wAZl+ggG2mOod85da0NNUyBSwh8lhKgvRHQI77FndGY6LReJhPg67ygUV8n
+RiLxuSA72wX+MaWCRvHIyXXEXAzwiLTjm0SYj8epvK8xf1/cSNQ9TrzMNvjxaI1H
+BI/x/WIi4ZvscbITYfyZjfyMskonxkSlUZrbNyCTw0zIVZlEmkYNX6FsssH5dycS
+YQOdIB+AvHBk6sJ6WOowHmeUmYi/w3hbwpIcr17FPvQL85EWbSmOZSxCpxOdur5i
+G0TIT5IT3EMALl6/knmYPcJNCRvreLQJcA2U07l9A3AxxFwnbCLaWhKNMYxb8EGY
+UWOSkSgtjmiBFmXOQ9DWVPCqDo4V9heicNkK30hGUMZZGr4h71qZ4Nsc1wVwzvkc
+UkY4TCPc4VUINgC5CXyoUx6OD3woIW2CDMtTRkaaYvPQfviWDvlVsqyAabumStiE
+cbjmjsA+xogi8NFsI1RsvkdleBTvDnjoea7JlE2Al1q/4VUm18z2cJOUMDMv54+F
+MpdBiJNCjRD3fpprKTFChRoD4CGgPQXnz5gU65IRl2Rc7kFbvGqWiXB43XYtmbqD
+XLQFvoL+C1oBuDnFPXiwI+5YIu4gL+ksHjCxf/O2rpMRwxLrNtZs10Fdhrc1c7wq
+g9cAiIrXIUDPYcALBOgZaEXHqz7upKAz0At02x1neBUN+IaFOXUnio1tYV3Flbs4
+2VE20ClzFFLANUKJMN7OdseMxGO8skJdomMYAsiRHPWxjBg+7DsKyFV7xPUpEid8
+73VBpk901OnweB7ml0hcrpk6tBP8Bm1hn9FJTNrbMjOleNSNbYH38LoDx8nXKRtn
+GEqAOE0U6po6pwnQAWDvHjA+TwnsvSrhNJyCnkFcX0P5AfuE4WhIp3xdGWWDDHU6
+mKd4AHuUxOfCyXH/M0IF+x1xXYfEjgpt6Q1et9IoyA9Of8owdoDOcxt0WQ5D4/rS
+QKYjDIMAmtrZRshIHAqeM3XKJinnK+DVCcgWJvAFXVWlhs/pH69hhil1x2Ksvkpj
+S+gP0DZRiesweoNtdepamW0MUOchOeAPcisU8w8yYSzof8xg3weZYY/4HNPYkSkL
+VdGW2YbP6amxdtQlOwr0FCdyy7pDWwXwQPpvactl2kTshaBvTGTYCzlOfD8DHag2
+HpwLZ0cMP8Nn+TmNg76RUpxjB68ywl7E54motksk2wgFXB/3fMLh5iQeyLYxkSwz
+5eNhE4UaVlbyXewz4obhL2BP8VDA+a36aft59Eny53/f+Up2P/04Xg5dsGOSaFi5
+FlMexot//tzT3/6AhmTleP4prgVtlfVkpfW78jjXwlFIp2zoe/Xrwc3/M+3uxiOg
+f/xj5yOgfXn/SB7+XQSoKnrFDC9+HrfE7+7e3Mner2uJ5/SmZonj70NL3JLwv9OW
+OA+Ci/FyqMwtB6ITsJYw0MwCjVsFrc8egVaeoJVoGRZeWqMuUDfZcI0oAWsOuA+o
+GiwaRpjDhsZYwUtuDOoQBXbGocG1Lxt2FdcJSUzQSqLM10Gba/TF0Kpivmq7/gat
+WpakBLgs/0BIDDtjAhqBBBouBvB1jOc0l1kZjQZbwqwVBkKVoS9/+cuvwG2Kftz9
+djaznQb07W/4GGbbm7/dj/oeeTz42GvGTwO4fD5YzwXoctd/iDY7bzbL+anWRZlu
+5b7h8C+kSuW1pyJ1f6WIy5ZL6UpdB/NKeZEw8eBD41St8qU8J6+CPziWq3z0Z9Hq
+eh3421eim4uOf183GvVX3vaeHyO90qUfKp9hgu6jaVBLEvQes5hEs2ibC6yhGs9b
+X38KtSju91NvvagEA566Q9DIM1V5f7Eisi/fvuEi+/+RmwM5qCBD18ztm+RIRpKJ
+TBIn//mmyEhi6XSkpSQ2FdtNNgRdlT6jYA6MPhioesVjMH10+ybN0JRgoLaPZcuw
+dBppEsXMBRa01YZgcroTRXzTbVTfrCZcQtiADeOxcE2aEmapiB0db9WzAZiHCmGO
+hFkNDAvMIsw8YRkkBbWPuATMxQ2opNxMJjyi2rB21B0wyt2wEkFTbcCIOw5dw9Iw
+g4NBVMzuYJAd3qJnJpisMH+wsejc3Kq3JXEIm4xkGz66hThOpmS7E90CuDcafMso
+3p4HU9NCd4VlprntjsGMyGiMbjM0FQgbK9RNwl+iD5TPMWb/yDHbApiiVbywPZh9
+loR43WgSNcKU5AP8Rg1HhfUR3yo4J0od7qABdwImo2y7g7a2arMtNRyJuL6Oa4tz
+QxQSF+Mt1gBpRm2OB0wIii4npAuZuolKkd7AFCrXD3GqjTXa4+QwpFWJgglzI9ag
+GI8h6LiG0xjMtY5vJb6eZUrNOWZ87UlODafot9IeXfISqP1kdLAGrIpzcw1ACTqy
+Bs22arMtNYhG3EQ5XAPC+YBZ6HY+bIsKmUpYKPr1a+Pl2RRMlCEcZ8DJl9EFimZ9
+ZZ6jWr96Y+3lYezIxCUc7qg2HrmOU7ij7iTnmUEO5ljlbkGi4U2Eg7bIu4zE6FJH
+swjk6VDx2+OV+T9/FoGBFY2tOH8UVgYaHNwcwO3fm0XTYtuS3t5qmgLFsF+Vm9md
+F+h3UHo78/ykrCxJ9Y0SN+d9o7v615U3Cz6ug/xr7VGYep1NNHsIyk2Ux4jVa/jL
+5awKhceiNKDMvG2tK/42YQPQvbf2l14NGD/4rNdj0dpf7qdCvnvTHNjdOlj495+9
+zaao5StTv1lrupyGwfrDbFfOED/VbKDuR8HCD6rVePheYy53wXq7/Dnyl0UtbeoH
+fmOIwTxYe7NycVXdD67e1qvMvZnnV5eNU0C90jbIvM3Py01QJ4iD+bydRZvK8ivN
+weXL3fpztCgJ6G7q3/q3jZEt50G49hZehZJQl2rgvVwwr6STqaRLehPOeuuF+5Al
++epdEx2P7dZlBfnOe3snNzoJZpWVn77RrhoVbmceC+y1t9h3dOdfTZt8MfcW4XI/
+Me+ulCZr7OarJFo0IIGp3ZidqbdOPgfrKI0WyT4e6+rdW80PmiDXq9mest/cXd0G
+jSoYhxVt7j9j1aLmraa9CxpsmQbRevpxHQTlbGjSNHjbgFdEwNUjm6thJ08OqsNZ
+jKYHPWDIxT7JJofZqPzXP33tULGLBKL6iTeOVuugCVM8rsbDTs/C+a/VQNV6CzBB
+3lfCg7azb38TUVubV/Wqf/zX5eXlv//4+uv5+Igm3779bR5MI+/Vftza22D++uvJ
+l+MrT01jhnvp+KPt1WfSjz3GDWZVfzM/5/m8k3VOpxtppIrt9XtKMH/9vvHqY1Fe
+sQ9FCKp4Z6Z69ecgj4gu/dDT21OMlJ8emwHi7HsH9ZrfEWpYxBe+OTvcsSWm8BKD
++A5JTpWOkNy5FHHwvP0+or7xKInvrfAlGhbscSkTsGpvL6UroNBOhPgD8xenX3Oo
+YXw46iv18p2Ktvrrr5f33ka8q907zH/au1z2Z16+3G37yspbBJvCYSBW5Wp96nX7
+Kv913MBCH0bzd+fT5o3aldKznjf/up+GN1008QwT8+b0xIiaGIZWmSR1lbUghVGo
+34tUnQkqhBfMX/e8xbRX6VCXOwhRBNAeBtOK9Md9tbWTK60DnkiaKw4ElCfmdyna
+X2ES9A6SF3PIXWj9/nx5W+OUivrQhn+98da7nQXb89sjd6t1GNNgk3RC+MMf/vyn
+/9XbLHdrPyA8pff45+Ff8PmXW299OY8Wl/5mczn3Vn/68/8fAAD//9L4wNVYaQEA
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /favicon.ico
@@ -20195,29 +20252,6 @@ BmoYo7BZnWNvyYByaSwiVovxu+eXw/bNTS8nc99/H+r9cXV9oDh4ax2qg5+tY3a/
T+8X+oTVYDZdjjdKfs3yXfRw9ysAAP//U1zL3LQEAAA=
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
-Name: /images/icon-konnectors-result.svg
-Size: 2272
-
-H4sIAAAAAAAC/2xWzXLjNgy+5yk46lWl8UcQ7Ng5RLs9ZV9gb53EtT3j2juOa6d9
-+h3KlgTtOBeKCPAR+PCB9PLjsgmf/+wPH6tmez7/+GOxuF6v8crxeNosCAAWH5dN
-E6679/N21Yg1Ybvebbbn2/dlt76+HD9XDQQIYkGseX4KYbkJf+/2+1VzOB7WTf/9
-++nf/XrVrC/rw/H9vfcKYfm2O73t1+Htc9WQNOHtv9t6ui03jN9e0tcvL1+axT3m
-x1/n7fAv/Nplzk14XzXfSFqU0BFENaWCqW7RWsTIyBks1Z2FDq2VwSc4dwokLYWO
-8hDQUmBwzgw1nsFjOm+UcEvie/jGFFWBkrRYQscYAZhLsRY1IgOJcGCMxVQT5BYp
-ikIGtMASLamAphYhGrBJ1tBxjpkUlagtEUVLYeYgGLmkDKLVeQAWjpAoJSstcuhE
-YoYiyNhiiqYlp5Sr0wCIJSYuVIyCwHg6YcSimEj604dUiaIlBtBcU2XMCMbVeQCe
-lT6jgioVLsZR4fDTUN4sGZ2ocJmTjby5KpkeUcEpdI4vzlPGE7dsvrrhdM6Oiqlr
-nEbeXIf5ERXUU0HSsswUxlJVxeo1JtCLTPiRyESryERnShet2nYBdQe91B20C+Be
-qtxLFVNkLlm07w9qLEUVgHwhqBGQWQr7opEjCqfCc4YQImU2zubp1KggVBJnT73E
-IlkEkfr+cKQCydTyrIkjnut3Hs6WmTgQxkydkpCjGlnB7FU3q3zGRB1aH+OYcPjT
-JPhk3NhMibsRczX6cZyIqDPr2HKD7Zh1l4Brg78xXM/c9eL6i4+YwFGoMJMYQxXV
-JMR+J73EJi8vMbT+NrSZ3Ov9Bj6g7qSXu4P28wHhlsv38QFwjwbr7dGo62nVIDW/
-vAyPHo0/+7/Zs3Q4Hv5fn463h4QxZsgIalWoVMgKUz/3jJqMUp2pAsRqJXAthQXz
-r9Z73AyCyuBRzfe44K02nDGDsCGh8Mo0mgVGc1cvmnsaghFKVkYMzGPKc+tQn4N4
-FVc2TchCQ2A1D9l5K46VeAicyhbHHIwciWNuZh3LniBemSsLyVI2lfD6uEV3iSwX
-m+enZf3d8vz0MwAA//8HVQVl4AgAAA==
------END COZY ASSET-----
------BEGIN COZY ASSET-----
Name: /images/icon-konnectors.svg
Size: 1725
@@ -20480,3979 +20514,3811 @@ fbMB/nyGU2acIccrge9x4SlhvazSKxGXdXxfHu/+BgAA//+FI4itiAQAAA==
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /js/cozy-bar.min.js
-Size: 411921
+Size: 396813
-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
+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
-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
-LdyHXNJHYf/qNiRTZJnSGzt0V/lSSUrfcKNHKML48HDetyXc3GQ7zXWGwF42figc
-PDduyyEHAk7rhkqxu97v6CAdyJBUuRnm4AVEBPuTL8NJOPZRhn3ikeVSeiRJJM0y
-j0hKPCIVi1PqES3aeyRPmPCWntZEvGXCvGUivCVbe8tUxLd/y4Winp573lJ6y1wp
-wb2Y8DuSeTHZGYtMzBT1YpHoP6n+v5Yi33kJUcT80Yq0lyReQlPPiv+Zl6y4lzCS
-irWXsDsvSb1EeXTr0e2SJt6K0TTJqPJWbF3XYrU1byWEotJbCbn1NhNv88zbPPc2
-L7zNl97mK29DSWL+UOltbDM20tuobeoxj60k2VKPbdce47tceYxn3u0y8W7pfk25
-l5IlTb2UrilPvJR5KeO33pYw7m3JztsSeettKc/NH6bo1ttSRfQfKj1O7jwusliy
-nfIq/zuRemKnbCuE7YTIla545+2IJFtvx2KlO7Uz/8XajNHfPLnzpPJkvtx7mZeR
-7c6rCs6otYFlZt33si1JUy8TuYypl+0I16xO8LVnDLJeli+9LN9uidx7Wb7zDAV7
-ygymSjxFH5ShB6Vx6qmNpwz6FNtSTzGlYaWnJIlvvdzLU08T2R1LqPDul9KLmdRE
-VNucvYSuMo+mKdtl1Ft7ZjNbo9D+aQ3+3pZkt95OZ6ks/d5OpPu1sL8mR3dLwJOm
-s0rsvOxubdrtKd1dv9598XyIcvwZ5wpXQrrPwJeUxCqs/Mh8WBRfjSfj5yh+pLCZ
-m//mZmeK0IyEqL9ILZxKH0YnPqAUHxwTRzRBlqFEE2Qd3hqGVO35TVBcp/yFpemP
-NKbszohlWf/bcY5XLBkuxgiXPcijNFOmZcD9QuvUEu3w+a9gFpE4plwVJGVrvjVP
-kixZXGimoke0iMmu0KRSmI2JYsXStFilQiTFSnBVrNP9blNshGQfC7vTUIg7Kk3W
-HWFcFXr4C72S31K1kSJfbwq7/1Boeij0aFnwnDPNi/Svyoq74s5IyMUdlaq4FzIp
-7iXT+mfxAOcvn/51cY5W+FCiBLcKVFGMaEj5XVGMJu0uzgZ0fIyMqXFfmbYACzcQ
-+MRHxnbsmrGm7obrH/9oSQnnyE12SeWn3VpqcRGPJidh3gm5JSn7aKGGz4k6eZGv
-//rosKYqOuFLo5WCd2RLS5S5QNRRc/RnTEsUV6az6tjpyUO2nRbsNMk+3oR2U+ZE
-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
-45+LucecyE/OSB7uchPfh4dE0ksq1zQxFPv6bzlJEdOchtTn5IYilGUWXbllZShr
-N/ZnIggkyBGBRQEIzs3FHKMx0o+IlObe+s8a6WNR6W1ZLnoXqHeCpTU5TBTm5kwn
-BTb6EBD6h7nHXT4cX34iNUaMWFkhg9ikek7bxMyBc5Jzjbi4Fg/rHQa0qx9WTVz6
-GrnO2QKJctuIDR4RkKMUoj0eMSBR3KA3xhKlONci1n4GdtjE3DU3Rh+zfbDCus8p
-NBvZYIdW+jnazMDgKtGU9vuK288GNEvTKIFHGVBo1zR+hxUSQQCc7CgpAYyS8rER
-zGcb8x4NfjWtNlhhENVNdFqox2Ssq5HdoX/VOaZrtLxLsjMDWvF0JNr0VxUfrT/J
-+pOeOjaJ/T/bl1Fo7g+030f+cOvrD03b/QVEBOt2M4gyLOxDblzhmtuGADNMY/Yh
-eqmFzQzlSH8tbTzMfyDe+33Ne9szfaq5O3MqvsPjqXj61D1zrOUCtgKyVo3kQNRG
-obXF3nm3N/yOpCypDsZqGXe/o60lmJ755lCmf8bP/NZkZM6VVvtLjK8dm7l/JsKh
-HZozc4y1dxl8V6o3w/QT/k89LWmCw+lW/vn9BeLtTqaaXUTKnAbYdinSXijMqJ4/
-DbSY/RYJE15ue0SpbQbi7vt+jBjKdIaGgltAZ4M4m72LMhO3vVYGqxuNu3u/r6J4
-OnRLk6iXhCMcPR/E0XMXR88NjjJsJ02zJtg7iDJkrr/prjOrFmQ3+zHaocTCdBce
-ZwM6mT1ECdo7JTlwa2fXefYQ7dGdhTta67ct4N3sIbpDy/9nfIyhua+x5SO/ixub
-0EGEA9NP7HdRc7d7rGe9RH6PIn2ILvD3QCFiPvUZJURX+HsgUI78ltbcuDQpegMO
-zo5s7Ufgo96+7WlXhcZF4fTWbaOjQTTA56N7NMznowvU5fPRFdL4jWLUxW+0Qn38
-Rht0jN9ojQbwG21LtISwLAGcVgfo6m29Txzjs2aVx4Bz91Be10NjAPriCHoI6qfy
-Uzd9N2GVXrz4jwXMAyIkj8fMg+HVfrsUWszszx9z1rM7h1COSRPcAMWYzVjzek3W
-kRPqLR0IRZXVczCGiJuD6VN7+WW86EaJG42dqzDtOpg30eJrFTwIgJqZvDyqLirR
-b0bN3R2boOp2Tm1E3gHRf1dXUaIE+/PqOPi7PE0XPtq0KT/VoQIWvmZ/p3GwPuWW
-j3GtZphT5JsoifZBsNeMrVJyKZzplkQrY3XQhd19OuRce+4ZcDMhBsPjVkGUYeVL
-9TtPDqBliwhb0MJH97gmMId8Lo4p6grft+Rzgy/65PWAK1tY3UQVkiNL8tacW1sD
-Ckd42TXVKXxXyUp9U964MuXd1LY239na9mEQKDfY/mnDCw8C7nqR8CComswhxg+P
-nAGZfGNPUTwbuydADgmzZb3hfxEyySIBILIhYiMJ4Oec+KhFqUNKs+x6Q/j/vaKx
-4EkWHQSnkZ/avUXCPeJl5ouPTOQP99PhEIucq7KsQDK/RA/dcib93EN5NiRdvbxk
-PFc08vWLR7ytefVR0z77fah9Negj7bMgpn3dcib93EN5yFLk6v/+WeSyzmZSvIm3
-EblsstrEtgD90VTp5uzlGYB+RfYtcEL2A7AJ2bftuhRcbfoN2+rEky0zXy023Mz9
-bAMZbJU/U3KEij0lp1GhP5r63Jy9PMfQ4o7KTl06oV+VSTvOS9KtyHotNUlHTbWp
-RyXUZtuDCb3IPjrikHsZarOyYFEUJp7G0Z2OdK4WM/3HhKfg5jHULbIPuhnt+bum
-Hb4Jmx+SJLnKVyv2MDNBHXdEskzw78Yzn3HPP5OR1GrYWviRLMtHOMmzyeAZssbX
-2v83wn3k/0CXPvIvNX78lztpnvc+8v8t5+avFldf5msf+Vd05yP/vRZX/Hfizkf+
-Kxr7xmVbl5UTubflyerxksh4Y4tlqVswtSXvbdF5pmzpiprreE0dwj69E3d14isa
-28cF4njuX+W6ROEj/1o//UWXea1r+0EDXxF/gaQB4waOG0BqIBMDmhtYZoCVv0DM
-Qpv5pzPYh+ucZvbpLzTh9fP1JpfV4w+S2YcronKpHxeI4Ln/8tJH/odLf4EyPPfJ
-1kf+busvUK7fwm2o3/XPAsX4cHl5GQ2YsuncrMpmygK4KNFlB9A5wDCnXcAkGQLj
-Fsyc9TdAg1DyCGoQjHXBXg7BUBt2NZcZgOeTZ9/hyYzMJ4uIzMeLEpHPzGIcrTOb
-5XPz5DpPrvPU03ru6xF5pf+/0n81FfwfPa7+4jiIGoWHeE7PfOEvhoNuD4Sq/5fJ
-2Owoqu+ejYtCfTsZw+yeaflU/ctkDA8mPtUkqtt85mfKn5rEZ04iT6rE506iTPyy
-fVMbvwR8ThdAmRA16GBFAUVlFsWVXKC0oCluKc9+pOvXD7tIgBiW5XAcb4uby8sK
-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
-lDMNd7NA+AkkxF+ZNGvL0NXIi4jB7r0sJ+w8ZrXRE4wIoBz67r3Cs8ahJ6ahr2rp
-ey8YnGorxnsviGk5x8zwkQydCcGUycpoCL73ggHTDhvm0UpnpwxkI2Z4iIsIsoOO
-T+tFnrI97700G42v5kRYYWiIGDQ2MSL83ps8O6H3IQkzfJ+Y1d/7Fw+JOngpHm/T
-KJSMZWg3BuKiyom5vIwb0qgDMUe7so5pYcdG5EuCyAAZHvQZEoL2xKM3LuXwuIu4
-oPKWaO5QrpMQHysyHr33MpHwKPrriSelrCnWfDXChuj+PYZDic9cFLJ82rgGcW6+
-j4WaBeU1vJDwuS4712Xnuuxcl53rsr+/Lnt4958P7z5/ePcHh3ffPbz7jcO7Pz68
-+1PxfOfbH//zS7/7/i8zuHl497vy+98f3vlXGf3VIgj96K9+8Luf/+/D/b8/vPPN
-w/1/Orz79cO7f3145/uHd97JgOnhnXcO7z57ePdHsqy3jwbVpQlM/e17H/zu716K
-UfXw7v86vPvq4d3vptB6eOctUe7dNw7v/MvhnR8e3n02Btl//87fHt65c7j/yuH+
-t6aDraDxzgeHd+8e3vnp4f6rHz772r/v/93h/ouH+395uP/+4f4/HN75W8PW9b3z
-gSzrhaQs5/DpOzPg97dvP/3vd1863P+JTPDTwzu/Orzzzscv/ezDb/30cP+bv337
-Lz/++RuH+9893P/h4f4zh3eeF6y8s3/49L6ILxrilcM7P5PM+8Xh3RdFJfd/miX4
-t28/d7j/k49/uP/Rz+5kGuOVwzvvyVTvHO6/mi16rF6S+ATBpbDqBNPK3r9zeOe5
-fPosqCdJs8j+8Us//vAn/3sM1w/v/oOUrhcO91/96NlfHd55PoPukx+nY3ymyBTo
-D+/+jczg2cO7z8kqpHGKMf+3v/qObiUVr0CLlmV9W3afl6UUfOdw/3uHd57/6Dvv
-fPTG3x/u/3TWKPDR9//xd2/+i2zq9w/3v5eMAh/+/bcO95/58K+fPbzzrcP9fxiD
-e+Nw/ye/e+uvP/q//3i4/82Pf/j84f73D/efz7ZA8YBwuP/cb9/7QIhUpk4Trfn8
-4Z1vKIT68Gsv/fa9vx2TlTGg1ePD4Z1vf/SNDz5+5S+12D69f7j/t6KYDAKIjDIU
-GPl2GqcjxqAMc+IhJSe6ccEzxxWNOCLdDCGeoE10i/cTsDjc/7sPn335d3/3kozz
-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
-gtWyPblqbVkl3iDNPFXUFR8zmQrs0kGKAmcw0O+KCNW1LItN2WzS3DJSdoVGF/al
-3cwmMjYp7+jjNZTJzX0fcmj4aezETrsk2b+q405nfypJad2kEivaoqj9RNsUEi+i
-ZAacgrqkxNmlPJssq5TnkyOovwQ5/KOlPGnzlPaMMKkKPIoIYtj7Y6uDzn1SOCQS
-xZ/z3Je4+gij3aN79ESlDPSHrFS8/1FAcWyhJ5cnaqiRabYm2NGtVSuV5JdM6zUB
-SkAl/pyDmSbwMlgURxnDp+YwQ1shs2P62ogr6lR3aIIwDljTAZ8RPcXrrIWtmvBd
-z1GltSyURkZ9o0d7USDPshW2iRjFPz3yFxJZlKGhTTpDAxIjN3WW1gcavM2Ud6Kz
-2nySe7EGpAc3G5XTNI4DZC5ZBqf5jLN4MqdsujgvKY9pJolMuqgsP+losYSmMbMy
-OllUHD8upo14fNqHuNJwPjVEK7kuSft6rMPYZAr724hzNGU+wTOS65JhzPYwLZ26
-8lhQrnRaUDqdUnp4VOm6m7hUlG57Nh8bgnl2aLGsOEaC4UmcHIQXE3OFSONWI17I
-zAy/ZUPrjHKgDnvIw61+MmCHyhzPkE1sUGbE7WXA+DxDesyK5w6gBNM3uJS2Vsbh
-4/DxwaDI+KDkoimz1uOlrRcU9ggmmKOiNJMapWWViBxZUElovBX1sFhdqgyPt2+X
-mKK5lZVqbbF6rGRpLdHnk4WEzHSFiNxIjSzwY85Op6/Xqwnrab0NcUbMV4vo4INB
-Op2/BDnKrTE4K3p6pHis95pcbUQ4GIhn/UnmJ6003TTGSm6FPl6Qb9YamcX5JEJT
-KrqhW6mHF6J0XSwUCi+2USNqhM2m6CjQ1S+2A5gNnWQWCIvHksepoW3UDQ1yw+IV
-Ct2JGg19tld3RaODiTIRDzDyTWeawW0iFGIYXUE1KAM/mTzFk6rsTm8pu3ZE4/Ep
-DjvuMsaZU3pr6uwUq3q1rMfszJLBuLEo2OMMd2toqB8mlxInzEtFPDG5HA4dcCSt
-hYeaBQimJ1dNoDWnUkVu/Yk+/whlXcj1oZYCC+ljnYG1RX85p8/nnnbquawn1ycm
-TtZVC0/WVbMn66rNGitfuvzI6pNXb25cXX38UYAn7D1iqJVzvZVihoiomgskp4VV
-xlSuSkahrAydGmrwpksAGtp7Q1GcfbaiDyjyBXMJEx/dNtVaOFKAyNWOirSETCOj
-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
-vo9r6uJf0tTvUPv5y6b5crXavKn6TdZ7TQ6Jg+rTS/5xLV39S1q678NycKA/W4+W
-TXW13dTzerl6W1x3GX9Xc7f/qub2HW32epYflmOtYht6N5damyPONn8XSc7/5RzQ
-evK8S4c/pMg/9ER7eK3QuX3c1MlfY3UWTt8i//weijxtaDvhtBtNkzlpaCZ1u4gd
-aWgSUh30mjR0fzx3sQvS0P0x0MWu9mIjCboE5yFBn6e66O2HO3gkm/Ld71IE6t7z
-mI94xuM4MMPkkPnLThs+bhwzqdLtcx4oYxN1kyEjneexYQ09GUOT+R3dmqyH0pXD
-6r1K9u94+JRKvXMAj+66wkWipwcWTutna7p5BVM2dPyzZpIHx8NmsoZ1RwIMSpLH
-T5py3EwG/+t/ZSmefqgbxI9mAtQx0VPnujn40i5uND7/+seX0+//8uPXf/lxQJKH
-onEVnHqi1fLb5PxzVZ03aG6QLKp1U9Xhu0areWiF8GlD6+rselHVk4fyprYhTe9F
-WDrcyquN2z9h37Z60bRulk5xsyO249mey7dbUpF/4fOxtpKkrWFZjiuIubi/2wpA
-9ODcku6KAFln30+/nH09GXTfg8BNs2P20AMrbQh6HKxuoRUPzQeta6j0EQ097nmP
-gxoMymgP/yDnFHETZzLZPGtorHEg++y4vfd/wuPL86pZXH653e4mTevbaxK6P9jV
-/nK7nTT0cr77BlJWZ5OGLndfbrez5a5B0HJ9ETJ8u7mqQmqgBqDsPedcDtdDi48z
-l9FX6tN8Xf6Bk0ObZX7YqVDaMztsCfe+fegqG3zZjgmeuzX123RX5EV9OlyWeEEE
-Cbl/clJgo9FzFjoTDRdgYtz+Bv7uwAb+pj0U2DsQ2HQHAuVt+RRy38a05W0ZvCjt
-Ji8Gu1ZTGmzWrzbz+gzfZvdWZtlIbuhudX2B5+LRjeMtWUyGXS/+Ay9nT056vI9b
-Q1DKLhLkxWl6TIRQer5cNVU9PGCAMNTy0WQyrOhlYDTgk/iJkUCUlPrZ+g6uzk5b
-RZe7jrtvy/E6Dr3EwQfv6sWiIOndAXDQGhxUcLlLaSBjNowOl9HGJxncDcKDGXqe
-8h4PisHjFtZnnt5s+9evp1//+e9fv/zyhx9ezv78/McBQe/5+MJ7NXlvtm+//w7z
-Brf5X263KG23wDOtCDk8q2Wz/Z//8s33zwfJ1d+42nP6h04A0THoGiV5J6fu3n+8
-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
-/rTOpsIVeNXEnPvw153efH8//khWZVfebEvfotktmw/npK/e7JazV29q6fs2u272
-6k0u13jsJ22ifmC+DKRf2TFzK+mLPGYTlexVn10tx6GD1GOWD66avhe0n70MtFtL
-3wvK5+6l1+50E6eV3b1s2pXsvaDd/exlIGN0++YrQnomZhPmyu2tXbndtSu3u2bl
-Tiu79aU9qitvtF11O065me3WsveCeGs15Y2Wem6r/Gq+VlX5uuVB4fdCu1Lfkx55
-e2X5cM9eOX37Z79Q2auIu236PptI8kIVdLCbPfpj1NktiJZ2C6ei5V0OFLvp2z+7
-hUp9N1eVJwXk7OY6MursF9QYf996K+Y/x2VOntc1iOEvxgiv8gz9++z/ffb/Pvv/
-Y2f/wY+oefJ5eu25r+0XavsvnXtZKDv3ovV3L5x4YVo4qu45lXptvypS4nEBleaJ
-Sk28diBi4IhgZllpLnUjV7iWym/ILbhGSVdUdo32spK1/YLsXbxDJ15Trsl4+GW3
-6oqLSZWqU63slVWwm93deq3slguVmrO7Vym71brMrVTL+xw+nLpbq+25VbOJ02qd
-t1x2ObvrOtWD3YN9LnRXd51qZXd3v1xH1bKzX63V9w8OCtW6MKTsiScpCuLZhoor
-XoqoCllRhJzjvK90B67WdncPdiXLXBZxH4Qpj7e3t7tf3iuIV6FrbjXf+en62cpl
-qO8dVMRJ3ndqXBLdFREPnXq1XttzD1B5z9mt7tf2dqsFLtRXdysVcQ+Xpw4qB3tl
-t8ZTp5Wa4+65lf2DXZ48qtSc/frB/gFHrPzMOLXd2n6tLJur7O9W6iKzIuIAmn2f
-VuqOW6/XygdlVNFO6nxn6o5bqe2XKzy3Xq9W92t8X1SMDlTZ5Xtb2RVbqG+TiUCP
-zsFeveLWDlS93f19mVur1ffdA7OP0/WroZYJVQ7kwqDKvlMWITcOxJII2b+CKntO
-XYxB3rWvOfsiQkdZfairirK0Sh+IefEfujSf0361VnEr+3wHRYtVGdqgqntVHyqq
-oiyt01Ic+Y9ANAEdLeOagI7+OjZD9/GnXqHfqezvF3bKlf31b9F/qFdalVYWIcSt
-lPnxLFcOnL1qfbd+IINI1Hdr+wf7qFzZd/b29ip1GWeiVnfF9Raeu1/f3RWZB/v7
-tUrFbEHGjai44jW4slPZrXGyI0JA7FZrtQoq1ypOpVKt7tVEIAgO8bu7qFyriuCh
-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
-CpZnWbAkM8VzqLw+n6bRTlOl4qjv+RrOUIyJM47IkLMMs4mWKYsz9aKQDKib30/b
-BjP9KKGx1BDNbBvE2Pr/ibiJQXw0iyJC+YqJGuL9yFi+ZWagqnz8WGsSWOhZkNaO
-f0cEl7BD/fsdfzqNdwJG7qwSyDfetAo7O32ZFOuw2Ny6b6HnKJwQz7ojdCaaQ3z2
-Xoysgc/8Hb5ClscQC9iEeCEK6dEk6N96swWKbHtju8HdyELPfGUj5E8Y38+HYMDG
-nlWtWGhMgtGYyd/Z1KhtW9eTWRTNrcWWBZmursfEvyYTa4FCqMIUswWAjaGAM04F
-Y8zZL0+A3PnYn/L1Uo+zDhYoCyo73KzaEqvhBXf+iLyJ70elx7tJQz67gT597FR+
-n7+vXX99nPWf3MD/+MXtt8L70+qgOpjXq+15/b5/179v3xw+tI8OngZ3/eDk42D6
-+8cv4afzk8dOcDLyf/l1+ntl7Or04G4yGbj/uCctN2gfHT6ctI4r4v+b2j9Pjg73
-f5+/v/O/Psafzk9uzi4u62cXk+OTQOad/vaP8vUvlwcnd79Wfv9av//9l8/Byccv
-829f60+/3x3Mry/cYPDxH+Nr2om//fZl8s8jd37WGo1OL9rzf56flI6CwxHvo//L
-B9c/en/76fwfnfbNqH7a+vx0enP4cNb6Nj+7+Db6/HRSOzt/cNvzWrlzMap0ntrz
-kxbPqz2dXXxz261+3Gl9nrVv2o/t1qh+dn44P2vdzs5a/Xmndfh42vrsnt5cPrSf
-Dmudm9HoonVS75zXHts3/fLZxW3cafVnnYvDSrt1WekE71vtm9vy6c23h7OLz4/t
-+YPbmdeqZ63jp87TqH7C6wYir9y56Nc6T+1R++a2ctr6XDXHfKHKtc9r5XbrsNy+
-aNdOjtv8W9xpHc7OLi4fOq3+Qzs4nJ9dXM46N4dPnYvbp9PW54fTm5PqGa/zdDmS
-Yzmed54u62INjmoP7da3h87Ft8rJ8cPSPNtiDHqect34Gh2Wz1r9uP30bdZ5Oql2
-nr65HblGIu/s4pKvxUPnSOeJ9XjoXBw/nR29b6/bk6/B+0776dBd3av2Q+doea/a
-D+15rdJutctnF+3lvXpqt9qz9sVJtXNxW1+7V/NarfN04rZbx+v2qnp60663W5e1
-zrq9mq/sVXXtXs3X7VV/zV71Z+2n20qndVhds1fV05tRtX3z+aG9uldL81zeK71G
-t277or28V0/t1uflvVJ5S3u1Zk/EXsl1cs8u+pX2+cPT2VGtftY6rnT4WZdwOTtr
-jR46rUsOR3U+r3brs9t5upXwfXP82L4ZybrntXnn5ttT++nEPZFnqdK5OJy3nzjs
-jGZnF6PHzs3nx07AYef24fRmlPbbCWoP/Ny1W8dqjQ9n7ae03/LpTf/prPWt3rkQ
-6/lwetOudZ6On8543fMaH+dj++LkiffbPuJw8a3SvuD9Xs7arfa8c/G50j4X/fIz
-PG8/tWu833ZQcztP38pnF/0nPd/2xWG1c3Hinrba89Obk8fOxe1DpzVS8x2l/baD
-2rx90X5oPx0/SpiqPWX9nsw6rX6lc3Fbbc/F+s/5edX9ds5rD+2nk3Kn9e3x5Lj9
-1G6d8LOu+y2f3pzU208nT2et/kjW/Zauc+e8Vu20Tmrti2P17bjcbp3Itcit44OC
-y8/1ztM3vo6105vbWpvjRrH/J/efRiHHtaNPH9+PB7+MRr+33ODiIsWrD+3WqMLn
-LdamxXFie9a5uKx1bvpPAu5btybcu6c3J0/ti8Pa2QWHj1HdhPvOET9HbQ5/amyX
-5vmu8vPduTksd24Ebhfwo+FenO+n0WP7qV8TeFzgSw7jl9WzVv/JwL/GmB9UuWPz
-LLQUXn44vbktt1ufq+3WyUjj9vbTZZ3j9vZRbd7h8HfRLp+s0IXDWbuV4pr20jyf
-5Bj0PNt6jR46F6PqaatdOb3pzztP/UqndSnXSOTdlvlatFufdZ5Yj3br8rH9JPDd
-6p58CEcXFyleNfdK4IClvRJ4xqAn+b16Onwy6cnqXvVNurm6V/OMnqzuVX91r+br
-9qq/bq+qa/ZK4PbOzeeHzrq9ytGFpb3Kz3N5r/Qa1Tut46eVvRI4dGmvZN7SXq3Z
-E7FXCke0bqudm+NlnNjS+KXd+lxO8enTodtp9RV/UeM4ribr3s7aN98q7af2XNBn
-wStcPrRv2vXlc36hcWLa77dZu8XP3eGjWmOBT3W/HL+0n0aVs4vLssKnHA89Sjx+
-OePjbF8cz9vzQ4GnzzieuzmuS7x1+NS+uXQ7N8ean6q0b9pPZ63jZZyo5nv80Hm6
-nHeOND69rLdbn2tqvrWs35NZ++aY789j+1zT27Tf+enN52rn5rLOaTlf/zZfq7Tf
-HA1oKXya9ivpR3vefhpVT2TdSrbOl7PO0+f5WYvjeNluRtNy69jeSks/hMHpk+Sd
-Tyv90tHNw32/+jv9NAqx9dfr57WckVfQr9PUbtU8Awqq4tWLtL1MHxLzNHjm8pm3
-kisFXCP/OgwniItjRlFhEllAJATu5XxDQkJciH6xgBS9V4qhfngX0NF5mBumGI6Q
-M1fH8xfvRiON5LELN1ceEfZp4rNhGN1Z6NnUVbr5t7wNY5tRZ7HYZOVgyArik7Nz
-oXp5ZcO6wgutHtJBFAaDH2s5q/RC61/J9Y+1LCu80Kp8n+bHGk7rLNRuCrc7t7x9
-O1vkPuiTjn9HXtlV5ORq6c6Es0zZ3dKZ1gu/sp8gNd9sXSutXHt1q7qCHri851Hb
-MvCxH8v5fprMRgF9ZU++s1Rv6zTGfnxCD6fT91H4EJPox3tarf1Sf+f+0I+CH+/J
-rLf4y/EQYnn4+vOkoeZWoPLMS28w16RXF8d1y/0ZsxYWPhcFyzsJgTa/AxdFIoxk
-NAjvfQigbfdDGocT4jz4EQXWt3BWiMfhbDKQhsLJpPDffVl6Zyoa2xmIlv/bsSCy
-ZC+WMgKql9BkAaEDvvPpbOiL9zAjRHlGOCATJB6M81OECAFsrnqXFl1EsVAJr3lH
-NEIB7lrBp3FIiYWs4JM/sJD11Wf9sYWsw+l0Qi5+tXrrXxplGEQ4yL802uAdpu6A
-0roiAnM5d8LEIs2Y4nEJP71EUPAXmQWG8hGHy8+OMtsO0mdHg7XPjlJl3Au1wVwv
-6wJQ6NHs+cIwMxYzWLIKVmlraHHtyey+FCc7Eg4ZDgtPwwcSHfkxAdsvKLo1CCwW
-Xk6nsvhrfU5rbl1fnFVR1mrung6z9gPugAz7gGk/jggw2AwA0xH3UIxpk3bdnsec
-/tiPDhkQkURpMwQUlaFzEwYUWBb0mPLwKKeGmLhLegCWZlsdF93dl/0701uCaXCA
-1CuINiOPIg4Y9B2OmsT7wTDH2Vh2ysjoib11bRswvMPeRU3Xi0oMIkAxfRfxDqH4
-Sks44jvA3tGm69Ed9u7dOxfxf7HbyOKyyitDEWyUSuHbqAGDbtjDpBuWWK+xweU+
-v0L7K9t8AF+OHNwMAJFRHn7MGVW+kMD4nm6IGWJ1v3+fDfZdd4f/HQ6HPQuFMtet
-yly3ujv8/n02JBWRHJIKT1bcgUhWXFEnwpZoqNrvyoaujQYDbHX/tdqPjy3Q9Mxq
-A7Irvg+Gwx58riwsFC+N8Ho47ImMfq6pmWjKKoUlK7FKUcmCVslqWqgvqw+JS+Sf
-Ya9plWYloHquuO5AVBSu2XFPHYHEgiULrq1pwZ8tiCaqv27Au2xaKBT3tmi+AQtN
-9bs7UckCTSyHllilSamPrNELj+EUNIqdwiRZeznjzxJozUJhlvJof55M72kivQtz
-T4b97ReQ8wuQA1xlzRSvkHK3aG30HunwJDiHWRQ0ckxMJvJw/uF56vdv/RHx2MKj
-C/FAIurjzJi9+lhSsMVlQSOOv8xjISUDS/PWPghVlLl/peGjq55wpBK+CJscGiIs
-wjQQx7+OZlMGLMVCoA3gxOCzD2BTBr+IoByIdLRhgsnRPmCS6StIpq/wX/3wzpn4
-d1Nf1vCn0/8qBLHwJlKMIhk4FhReDcoHInNlWBpasazjY7t/1FGCvcZTQrwXlp74
-/1AA+LMbKOaXC6xMgHX2z/+PvXfdbhtHFkb/z1PI7G9pyM+wIslyLnSzfRxLSWvG
-kpPY6R5HW9tNkZBEmSI0JGhbsvku51nOk52FAkiCN9lOp3vP7EnWikWChTtQqBuq
-FAPitVB5u3raPfca+fAAhEgDXIueTVWFcRJDQt+R0LN7dxZecSu/I6zutGBhaNG3
-Xh/7f+jUH0qo3pWPAEuyCwi//VGTmByUkkapu9Pkux9fo2KPyDTIyEloLPAK5+Mg
-dCl7sk2K91JT8B/pw4PKwI17DqNjVgSD0iWDcQ0xGFHMNlf3j5tC7Ju/fmqa3aYz
-uLh0+u/nrvmrTez4/ec5nbw/2Hw4/xuxf/50e+a8vrH37f1Tz9qcLt+sv6xfrwfd
-49vTfVZWf4bft4KJN3iJ39+tJsvgTX85b9o/H788Xb/Zt/et0N4Mwsn+37zTTe/g
-7OL6RsA5HxZ3119+/bL5sLi7vfzHJ9J//2U1eX/7pu8MWp+6l3fDxWen//7jm/51
-8264+DgbLC7vLi8+zobc3GI2OD/u9LvH7L3Jfgfnx3fs9+z9jJ697zX73Y+zwQlL
-680GJ80OXjbvThe95tA53pwuZq3h+0E4uPjcOl30WsOTTnOwGISDzWXndGEdDNad
-1tlJpz24mIWDzedNv9sLB5teCCrpbj8cdC/vThef20Onsz88h/aEw+7Hzek5qDxn
-A6dzO3SaAH+6GOwPzpvhYNFbny4um6fnrK7LcLi5Zs+ts/e9cHjeaYk+3J6ed/YH
-3Rk9XVi3ZyfH69PF9WaY/t5yOFb2bH26+Lj+eMH6MWj3u/HvcdzvNss/XPwyH6w7
-d4PN5Sz55WNIB+ed1nDxkZ4uPsp1lNfF2u10WqeLz6L8Y9FG1t75y77zdvWl23Qu
-z/s3Hxa3N1/e/7K0Nh3JFOZv4aR94P4OM5i74eJ4dnrRbw3Pr9n6aVntz7MvSzeY
-dJtOf3N8Ozhh6xHW10vz57+5XxZNp9/uOaebDqgVPnDznt2TmfHN1Qq/gwRN5ERy
-BG2gjqhveoFrUqypZdGAcYMCTcV2PPIN7sGl4QR9j+IZ9lWv8c+QUFM7ip9etPAb
-rUHJO+cO22pb00U6csoyh4E5w5AZnkoyQ3rxZM2ZhNnOTbmRXECJb86wEiHyDHMy
-KeceZQRqhKiqiJSr1dxn5xG6t53g+jNrn+4g9vyRdVT3I03bUptPZj4OgkKl60yt
-EzOxoHTQ0rzTfbR0PF1pKhE7Gf+YlfUffn+EbRO4POKIWE4aCmFMWs0D7XdcHOkc
-NNGq6vIFTiVB4Ivuz7uK4fyvvYqBcEoMOg1hsHoW0sCxs3b5qiPMeSdhsH54iN/I
-CnvYBv8RDZ8Q+glP2XqlpuMFKm5Q059hqgF8YuDNStDZyoa8+k4LvAAwKpWtV3Nm
-8u0EpriUzGYuHmAv/H5L4PfcEviWdwRKJhDt5BZEzFjv528K5BkyaWFQLR+iyZNv
-tpbq8XKLqsnwvaullxCcxsT0zynxcWOKqTU/x5Q63izomtRUk+sJmaupnoa2rdZm
-fB/h9SO8ls8YLakBhpc8Iie+91QylJlFL7/w+06Ohpzv952+xX2nr7/nZBMLMEtj
-Qux1w7Tt3g326KkTUOxhX1UshkUVfrEli1PTux9JPb86rvvZWz6pKh8vyQ3+itqe
-cNMEybd/wC8JRYT9hQV4Hq4YR4t8gzaId0pmZyFFjpHe80CB4cDhgCzDEWhAXJVP
-92Agbb+EIX8upVpL6E5RmoJ8PNUz0pr4MDJoFKHKGiYhpcRT0D24N0xe43sb0PZ0
-/6Ey0lc0YW9CPQUppu+Ye+z884kbKCnYiqz2pOZyODZYSu7yCL/aY5GZEiFPhYsm
-yaApmoaePVis6lpFMxz7kRbOHdvGnqLvWBFyQVpSWnmYXAi6j5dGxm6g1FOZf+Sr
-bF8ma8MlM4Z+tQhlVpxOkLxqdDfKXFzJ8GhBlkdb/UHE/+o78Y9MYxUT/62XsSsh
-DVkwOK8ZE+3CY6f1UmYIVs9iCKbAENjfGYLvDMF3huA7Q/C1DME0wxDwC7XADRyv
-VsGfxAV8p/e/0/v/6vS+cOhz4VAXn3nclBhYAHO1GvLL4ckzN2FnHABcDP9g0jkK
-ZHYgNALODqyMQCCBRyl+z3yE4jdXq0DZVb0jBZImps9oVLwXLOHy9lfyAW5Kv4re
-6QRl+qn7KO6l7iDYxGElmyD29ir6JuQ6dLlIqvPkHJm+qu6jlfQR7tBvIaEt4nnY
-olkVB5+5bKjXJDXBpSXWwlgF9wcJiAZWkJGm2tofrPP5zyHJfU6SO8aKq7s5SR4I
-kjzkdPi+xv18HqSU+avfQ5lXekiqOqv+AFoc/S+jwktpVe376f/7T39fPv1Jevo/
-2QMLWN7PyRIfr1ag5oWzjRg4PoLBajg+KM30WRyUgfCrAgelZcR0MVqB3nhqwMjJ
-nklSJuy5Rwh4O5lQj52UU9nByc9kiZ/i5AQum0GDwLnLtir22JAoW8pLnZskpywj
-iHemWxyiBCvTe6RrewFebfV88ohoj2zv1dJ0HhXnyScwF+V5QpRHQ0p8x3QVXQGg
-aHt3+RDl2iOTNnAZMYidwrRfK8JNzLb+bx3DPc+EWZserYSMkU3jFfitUTTdPDLh
-IoSv+9U1SEI/uFdpHSmUrBRdmRBKyVJBFnGJrys/vDl48+aNraDA2WBdabWVLQI8
-cyv1IbafDmTKDMN6BkvVnG27RK5ojPywcqYb+VieTzXY6r7pTH69ndnLX9ZW272Z
-LJrO4Lxz23feupPl8ObLezf8smk6v/zy6f3pxcz5sOn8vWDktfnbLT7J+LDZDLy3
-nb7ztm3++sv+x+WbzofzPjf22fTZf6f/8xfX8oarSbvzpr/ohYPzxNBri4FX/3bQ
-PYZ7u30n9rez6kzeu6G5ze/OxfXB2fkbDrdO/dv0z5u037PdyfKX9eU/Pt1YCzL7
-3Kau/X5I+t3Pd6eLwezv3c/7w4uPzb+fH9P++2y7LpdvyJdfW6vLXw8Wk/an1WRp
-hZftN/R0f+h/+cenhXlyTE8v4M7xrN+9a5r/+BR8uThYXbbfhKe/Dm+wd03N92/o
-l4vbG/u925y8/5y07cv7XzaXm4Outfxlbr//5br/s72y38+S9p1yA6jN5SYpXxi7
-JYZRcbrXf+9efzg/vfUOzpas3sk/3t5Mlr+E9s8Dp//zsGkt3/hfLprOZPkm/HLe
-n1n7n9aTNnVP/5H6KIqNqp5iZBX7tMjW/7fFpN26ZXkn3qfNaXvuXv76ybWc1+t/
-bHqPG2Y5HTb37H/QP2neDdL3lfCJNJP/f3hvzcxfP77pL93FpN2hl+03L/F5i0za
-Ldb2prV8F1rtLzfWsvmm7/G6J+/fNb+cz7J1dXtr8AfD3k+us30rre/u5kv7dSVc
-bkyCSdu+OW2zteDeXv5j2GRj+iX1wbStjIX5j78tJu8/83qv37Qvf711JCPH9dmF
-/e7TohenUcv7JYjnGS9/WU/W/dnl/oztv3bfebvAF7GBZp+nLTqvT9vDlbUcBl8u
-imNcGIOMD5PewelicDfYXDZPu73908XnNhgP9gZ3Z+edu+HFoDM8ub0brjudwcXx
-enhyfHd20tk/u7huDR2eftb9fCvSW8OLz00Bvz9Y9DrDk7fdwcUsHF4MmoPNZTC4
-sMLh5rhzdtGf8fTe5uxCpC+um2DgydK7182zi75In90ONpezjxvWPqvD/ZL0OqeL
-/uase9nsd3vt08X17XDxscnTPzcHm36n3+21ThfXB9xXjJTeG9wNzzu3Z93L27OT
-W97u7mB9dnJ8NzzprAcXvbh8VvYGfFacQ5/aZ93BPviguBiEw+5sPVx8jNveHi5m
-M55+2RwsZqKvvdtBkv6xNYjhN/27s+5H1qfN6aJ3kI7/rDO8sNZ8Pc+awy4v56wL
-Pm9mg4s+G492MpYXlxs+xv1weNFvnQn4wabHnjn8xXWLj+VleHYxu+Vj3A/Puh/X
-A4C/DM+6vRYvZxAOup/53Dqd9nDzsc3mdrDu3A43x3H65uxi0OFjc7w/6H5m49UG
-P1IXxzC+HP4Syh4sPjYHDpRxN9hcHwx4GXeD7sc7kb4edi/bbC74nv7cGogxHmw+
-r3k5n8Ozi+M2Xzcw9m3w38TSux8Pzngb24NNn5d/3ukMF71NPFdnF/39QVxO97Iz
-uLicDS4+hoOLy/Zww8dmcNFr8TmE9Ds+h5fhsNvbsLH/uOk1Txc98HnB+/vxbrhJ
-yrkVY9MaLi5brF/DE9bHy47o1/4QfJCw9nwOB4vj1kDM1XAxaw2gX2AM3E73w+xu
-yM5hmP/ru3iuhpvL1jDZD7PWoHstxv/ylvsLg/TmoGuJ9I+dQXfWFOmbs+5xU6Sv
-Bwu+12F/bz5vxNysh4vrzZD1Afb39X4yZ5tjWA/DdefgjO+r9unieM32GOCMk87t
-Gfe1w+bggOGAM44b1gO2R0/iuRmw9nTAKHozY+PZOmXrmvvRYfCbs+6gmU2H8tvD
-jdVJyzlui/JZXQdiDm7PLmaAR84u+p1kHW6uNwM+j53TxfX6LBmfwcFg01vz9lw3
-h7CuLsPhwmoBHXRxDQbiZ+leabJ5+bhhuPPj7WDzUewta5+vz+tw2LWaA4G/Bpve
-HbTxvLNhuFXgx5ZYn8PBohcOF4PWGdTbCwcX1+thF/zP3Z0uPu7zdl6zdbuB9bY4
-ZuvhdnhxGYBx+uZzW5R/MOxesjHeP11cdtg+532dtdlaZmuTtXHA57U5YOu5y9Yv
-21s9wCl8v3wMh93ju8GmH7A1MHA6B8PNcfu0e8lwyT5fk73wrDuDPcXxonULPnIu
-jkOGG9iY87Zd70MZJ+DPZ837YQk8f8z62hrCOPXCwaJ3y3HijPWvOYT91wNj/KFz
-zPp0MLiAObs7XVzvD8H/DeyHNZ+bfnh28XF/CH70PrNzZsPn8iPDaQzHzsA/FccP
-rQHDtSfH4B+Q497jzpCvM5HWvz1dDJrDBTtj4Nxqnnb7m363dwv+hy4u+Xvvdj1g
-5V5YDIetuc+ej+Fgcc3PtsVgNliAf7iAzd2A4VR+kSFM8HV31hQ+B8G30WmX4Zrj
-2wGcQf3m6eLz/qBrrXnfP7YZTu132fq43AwvZk2e3jsYLD52YgP8T0s3mJw0JZqw
-v/h0/eU9+7+VLlzc3oBPye5WWoL753Ge8a17e/NlkylThsv5+/nDDPO/W1BkLCgO
-Eilt640WG1F09lsaD2/9qv1Vctoky1RElIAb6A0nEMErNTkYVVMKaskHWjukP6b3
-4Hd3NW9ExwYepdfVvXgweMFTnywZK57Ua//LimV5lMpWE63L705TwuPoqjkHDknM
-ixf/9eLFDCk1RWt4xF+arrPBqjJ811UkmFF8ER7uwY9ZBkWLr9XXFC1Cs9K47muI
-wWqMxsg3modspsoDixZTkyJwcg2RaofeT0azXic8wPs9mybd3/UQJexnN95YkRZp
-yN9NfB/stiJNcl9AGgHxqVoRXpkV+hOFn4iNgB1auBwWgoiIKh4e8Ch+3muNG5T8
-yMs44kGyVarpJRCUbdx8OlgqaghHaDTWwBiRf/2peTSKo440kTNqjqEGbaxjFEII
-mhjyMPzROtzdDTURCr/abFABJRqKi3VGIS8UwRMlmqahcLf1o1Wvi7IyoJQwwN2W
-aIlkbxM3uSSfk+ktSnaphoII3VSrY0CQjTzkC2vNP8lKKl44QRo4KQ5IGQpEEzBM
-1zy0fgwOrd1dLRxZ4xR4ZKVoxvANWyhSsPEMgyahT8EI/LKP2UlgmVQN2fT4SeQJ
-bxWCz+1/hthf69zRODZ9a+54M32nhabECgOw1UBBOJvhgHU1eLs+J6FvYX00RgE8
-ff50GuijccSKhoQAdnCDeAMe/fmdT5Y802OuWOI9PHU8Wy1FUMR3Zo5nGAYVjxGP
-betpUuC4QwqX0RqgqDEMxfEo9uiesus1HHtX0X1s2mvlSPUa8ATOgRr8KrVBRSeS
-lMaKBFT0RL2PUFyxpumPVMM+KvW6Fxs7+cFI5HDsMa+9mK7eO7bOCpAHPa5JSoo0
-xGPY1srL0fTYF5NLZqoSenPTs11s10RIbl1B4JCfzdPJ3PRmuBQl04aHb38B/0W+
-HKsAFo8XaawAC7K/Y8sFPmdnWcoVrygs8rnY9M/TLmUcO0jZylcfL4N4UgHvMLXm
-n/A/QxxQbJe6gAAaCHlGslYbU8el2C9fbbA8Iu3QkxCUKjWtJJPYmWYQODOPrReM
-7qVt1YTTpuQE+x4T5OuN++JYiyhAIbK+rY8FYUDXrvCgEFPk4M2ga1KsMaR84Swx
-kFAxNXUob1IyNqrQC8fFFDm2TiLkxagmNrpr62YcTYTNkGOj0MhgBWRlVnYVFnVs
-wzCCSONxTsSR0IDKdwyDHv2uJd5CcS9KN+49jxJhZfBbGLH9rOlfUXEpcoiPvCkj
-JIoQGqpsBltrYrRfPWLi6Hy9RwmtiLxOGDYsQV4MF+YxpcrOcRtPSOhZ2D6rxoEi
-NCHApwi14sQvYtRz7EJwz4qjIR26RgzLDuMX/01W2NNf8AB3npb48moE4SSgvnqg
-HYrF7xILjJxB4W6QCLsBrmUOrrSOWlxHTVV2vV1Fq1ngWpDRZhNcw3fYCilnjgon
-VYbM4f2cYXqOoVOlR1DGIVgKkBDU86SQ5CMck1UlTGC9sTzc9ELUDTaHRkVYdQk6
-qaQM9nnWdnzKJ6a/Z4aUiL7tpX3kAWMiFMfDMZ+lv3+8dAsixPqWzivgOn1Ifbbh
-4KOVWQRoMiX61gVzk4EIzVTcgOcsFtXAkF9M+pYh/LrK44JF/fFrvgkMydiqj7zv
-llR/hh31r47rVhlSgz3VUxA2hHOUPHNyW+dKcNQ+aJaYWm8x6U7tuw7VJnK5geon
-87YPG0VTlbMPvaGCkhiUEu5T8uScdBSYlPrOJKQ4aATYv3EsHJTwZTjhEL3GUqbJ
-Un+PcBIc4ufTATIvmjn+kw8aGhFxvvPLUySWSb1Q0H7syvNFIl27B6fnHieSOCWm
-+4w0o40rx0bAHMD6g7OMn6cJlaffR2zxiXOuaDov2DAF4TJGOWl3AK48vsK6nRuj
-s6mBExDM2QEvgDF7cuyDIbvgy1CQOdMTaglZCVfMhpHNa9MwDCuWxMgzzN1ZSAHc
-KFoZirJjGB7HK4ZhEDQ1gq2yMrybaUgsqENN7acmso17kDPOiWtjX3dVJUGYDemD
-oolh8lDM4erx1QF4Q8QDnrXMeLvA06o7TS1CxHvrhv4TM7TYvM2Ne3ELDPvbsHsC
-pOyqPtguJlPEw9SpDqSKqeJW/4K2qS4VABQO904w34+BJ1XIlPHJU/ogwUv9KS3m
-jBGIzy1qb4/RlZkC2X56ajmuE1A589PyyTl+dmZz15nN6fZhlE7qeZpDQYFE8m3N
-z+FiGuPw91F5CuKx+3iCEiEri3qfQEY6U5+7yAeqDQV07WL93naClWuudcUjHlYi
-EGw84aY0neMl1ucZvitAy9CljqCJ2Tm+5czTn3yYoi0Mll48WrMAqIwRKuaKv6Ai
-K8CBi+molPVIoQufUJFl4NDFdJTnFzKASSpHCR8YhtZtLuntsxR5MLnBMFxKjRH4
-zqped+r1nek3ImmpSUMZV0Qog83xckXXCor51adfgL957I5NavfqqZ12Mwmc/cdo
-fTP0ysNDXhLFhXqtQ/pjXmUA6kdBY6UaAjpOtAyk5ng1TxMVJGRzY24GZ7de3EJ+
-y9lDRAP9ERkbHlBC8eEVfddHaygA5fO+lqik261UJd1uC5V0Z7/5Le4Oxbl2mtGW
-a/6pQsR0b8118Cm3i//Mm//kPyAq+5wnEg2RND77u1QN5gQnxHXNFbx6SDrcBQru
-eza+44yA/DGZMOk7LP63eEp8/HnVJbeeiP1OGoswoB8Yb41t/gXiVnxn4f9FrkKX
-sHKELRBy6yV3k7sCeMC+sCkUwb7h1OXcETsHb+cmxTfYFywa59tKqOWyHBQvU4Dy
-y9afsIWdG8CeQVlIb7igmogaMmJOJHFwUrJ2hBvJwn7n+IFE2jD0V+TZfmrW6+Am
-GgosLG0RMLuqTFXj5Mst9CaH/FSsHanb2vNI0SgTqzvZ2fX6TtLWmLgrlOrjG2y6
-GYm8FlNaAaY/l21+tVxQ83llmxQX50cStKdzIZOFUiWHEPglPoxT9t83SKMCSyEn
-9y2LpFiJPkMgVfkfHpzC52wRmierbhPytmpstOirXQaUegt4yq5MagxhEkqbVjYz
-jDDMRu9PvpLYMw9pFFD8oSQpMUDPBoHddfHu1+s8kAQntlXf8DR0X3XK4G1HDC05
-X/woI0mqWqaV0qUdNU+ess2dtDilT5tj7eFBfj2sGCtJflg1Vvff+JDFR3zEs2OR
-28xVAlxJqyRTAi2pLMslAX5WUX8AFZElVJpS8zLM6NNwDuKKO4kZNbyGzK4zOrqc
-b43Xu3/kqGSEx9qIjnUyomO5Pc9bhBJyg4vJFcjNy33LIbfsPvT4mihy66oIpFQy
-dsDIv11DceXjmIQXkdB3sQgh4s9Wy/JX1Nv3bMfCpcd5bBsyw/Q4lsar/GJuLFEC
-20hFg+EpA5O0dBwykYTLK1PhUThTl3b0aGX6Ae57VKWo1dSEajm3YBMYj8Gk2H7q
-eNIECTnClg4e2gQCnQkK92kdiYXU9JAatLEyfezRIbFxdDt3XJwUph1yejlWQWPB
-LbmOdY3tGuaN0xWENZSJXxG6NuNjWF9qkspaZFDS2Vya6wk+MV33TIihq84X6TDn
-iycV2aDkdIFTPBZoH9IdOEQcFaP72GxLp2iJ6ZzYYK0Vt6KUoNq2qGQEwK1sk8YQ
-9hmi/BVKBFzBo9/F4y8dHUT1M6v8Y4j99RNcEkiVZwpXJYKugBgfHrDWoL6zVH+n
-s6AsKqRCtAbSs4S7AK3KNrVdkGSUZHJhrKzh47oyaBbP2mkmWeI3Z9lstOZboUR6
-ODNoA6Su6EbA5OSRS4NWSRjQREa5t8akkXDE6ATekpMGnRuTSoR8lfuWxQ3ozpgU
-pwwNjOXRVJdZkYpldm2EYj9cGGFD6HXQGTz/Ha+hsI2xhZVI69DQwlg+PNzW6zsn
-9foG9YzFkaePxujUIOp9hEJ0X9AbxeKQSp5BfBJoJCOxTni4+OQdqNearP+URRDN
-nAgi0tBFvX6hUg15bN8L7voa+dgMiKcrWY0OIIC8Dgu8ADzauiOx5bmuUNV0FTcm
-bugD0W1QVNX3hwcVN3iVqga6zkqBO7eKSnR1ZVQi96IoppoYA9VjQ1VAqSALVNjh
-pIAdxp9Ha5FIQ+QomQgvNxFcScgmQn9kKNhAiJUrjQRKuAvauMbrE2LjQ2HE6AvD
-xQ6PglXbf607U/VEY8upXldL1oasG+MkMLQM4VLu9hBMs9i5m2DwOMApaXj49ueK
-jR8UPvcpXvJvYRw4LzQEKRYciYe7o2v9TseNSqJLNVHA2rqFc2Mg6JoBla2QEHWa
-jOk6UoBJZDygokUUbEEZZ87lIrBoSyRyTVTukLEUuBVp3PujCFQGodja7Tdgxi7m
-UeMAbEQtTp1VMMqMM1/U6zvLeh038uyGqiFBylh8dlzjRrWqNomLFOxRUJXjUqWW
-SmUDy4yxJCcuilTeFcrQiucx9SFqirRKVPHYoJblYKyXNLLtV/qCCx+zcwjDujJg
-2A4F7cgWGcfbK1ZD2fgoClJwYJmARwaqomjp1laUZCNxkL0Vn/SnbG5u51he6V1a
-5+HqSH2kKFS2BlgDtsqhzur1M5VqUaShoREbHQs+BKgwVXtU7Zw61rvPKG9XCGST
-eg+VUUa6HydnBJjlWsr0u5RJD6QX8Iw9LNOP2pKWFerS15UC+3P5S4Ke9CtZS3oK
-3eLPXJYbvyKu0QZrqqW5uiDHkqD2gn3T1JmGHFufg59GQU8RH8uAn/A0krSbNlAj
-F+sVDoz7jKo8mQ5T3Gpkq8Hx89runM68jMeHK43lGgRP0hsIHuevW4r/K1cgTHDN
-Wa74+sB2o3aOsV6bU7oK9BcvZg6dh5OGRZYvlsQnwfyavPCxaVFZJfzDlkrYYCtw
-MFYr9bd1E8TQlaq0Ur3So8OQrf4PGoZsJWXDkJgnpKuDdQZViIvzYKUbtRSmbG/m
-IUsMIbIQ8potmCtUg0qbces0eznttyoUzVrJZKZlirmbmze49lfI8NeGolUUGBOp
-zykzzsOKjVAFJ5Mfy4rFKoFNCHGz1jO5byW4cevw8XuqcolP3hrFqr7djiiWHW+E
-cmuaP6qPpbV9u26WFh/3dJudTm7Wq9ReeTh+dqWJXN/ODqs0jYv7ImTHKbC4jfst
-KKFMhJSY+XwQshTcsOaOa/vYe5qJG0hjK3dO+X12EPgkHEtUuaF2WjkTtNZ2q6hm
-9QjvtMSoJo4fgQgAV8YtJTrkd/DLTbKrNFXGM9l1Y6d1mJrt0IaNqem4jDTmT4KT
-fniIeepDwTZ49bq3Yxixau1Qk0St3rNErUBnwz4rU2lr0nVC9UkdamqHnuHJotsI
-VZJSmfGKhbv1uoozWnSDahEqWPTBoPcYt2LIxkXSLSaZv/UND0hBrljYzo8S5McV
-Vq0eI8P2bCsMC5mYvGyPmlwm0azsV3YxbWOtmiVFbLmkFu/yop46l+mQ1us82k2V
-KWXpsIuSQfRdJavkwvAS20wz9yFHWR469boDlSH/yEyEN40ct1siOdkLRBVP4PrQ
-I0xZcUBgRxhlF+RTzVzVWLB1uQWDIcfICVeEZknlt+8LChk1xhSahkzDyW6CgCXk
-RLphvgIusbGSNVKkE9WwSlJhIeH9/4mSirAgqbAKkoogK6kwE0kFrynSEHl4KBWx
-7HDBUV4kKgk6v0aOEc8/K6JyZ6U3OmLlC31c+QIaWl4weGiuFi6hwCCqXyl/bqE/
-XIIaRBqC7SjJl7NGEOksm8moVW+sM473TrF5g7OIb8tm3GnFBSdcvlG84HtfplzV
-aXZrVJySOk1PDSSfOTkskn6IoaAnWwU8cpeRhPfLigbVCPEuSGjNz6np0y1AnPTB
-RRQVJbNQRRAaZdL8HEHIlnKOIFSbKMYW1WVr6n22JN1DcTk6Efd+sSza0qJIMh+3
-q50iF4wtsWEYVIttdw9jdCwsop2pGus3GbkUw6WkGDGah+RH75Ds7mqstBEZM8Jk
-RMYpbGIY/CwT9v3vJuxF6+qisWzBE1icn83d+Xo5IS7bl75Jic/axVslAZaxlaMx
-IsZOEzGqGzmxToP662RoTBQYeJQrf6xqhzsqMVTTCMDJhKpp3J1Gva56sSsmmAkN
-7dCHBy9dW1Q7JEASS/45WBMcA0dTxzNddw1ePXZIvc72Dmt7+qRqCZAzVX3B5TqJ
-Tb0XQfcOS22H+96N6Tp2zaQUL1e0RknNxty+N/RxzeMXyMF6NzFEVzRhcP8feMvA
-5LcMAsNWTQ2Fhi1uGVjw1Gl34GYBfz7QNLQSz680DU3F82s5YIn9rEsHc+M+ynl7
-y14x+POuEHj/EcEDPc6QAtmd9Cgz/oIfxbDNuUk41iIUZ8woRp5SQiaDKCoj72VF
-Fnw8afdeI6f2MDDLOsMUdCB5rx9541UwmlNSEVbMVYMDLGGoY+8qe8purG/DR4qi
-KzG9pOxibVcBbxN7yi7lrQZSs8Rzk1cw/Tn0MjRqX77jyg4uROPi6vXkUY1HJ0tk
-f201LVENK43XAvR/XIlQ4FfXAzSPRM071fbWyMx+S9RUh4kXo2u85kYAyrHvk9su
-qLXT988rReee6aTvIKC5xusj7mlJV1Y+vlFQKIk5xHE1CsbqyEHmmKEuXw1Rm+Et
-a9Qco5VhjVoMNSddFhZoFUYBuosqTAL0VaIqj/FYrtQqBsQp1+GZYPNSXOnAeHjp
-LZ/8vCI+7byGAPakirVMajwwSTqI+eDt+2Wd339Zx5Qv6zjPu6wD3Aj2gtDH+VUW
-/OIEzsTFqvZ1l2Ywx7c7RsYgkSWJqyFly0ZkMsoyZfUQWRD5y8NDrnh5/WFu4Jdt
-FSSlrYqX53NuoTx3KPOdLx/BrOJFmG3K2QwxYNmb6rJnrZxyX6VaFF/oEQWdAv0Y
-h2aUS6+6/44Th7C8JNN1484c+7i3XNG1UVZFg51667ISQc8UaWXjE89e2QjJlcRw
-OccwWZsLnDMUNamZSzsqa7geD3PiCFdqJyyXytbB2jLA5kG6QQapefvaeAy3O6Nh
-vHPFoBccjAibXG7TWrir4NiJUD4AyVdqLsKI8UbWegSOuhKrWsvwKo9i1/BKj2Jk
-i3o55RDffsi5ukHC1HNulBNPhNFMaG3MdyVSyYfEmQGSx7jkYLu6TF3vKpIfjri0
-kzRpVq8XUkEhoWioqvBVavcjsoKZY0HJHAotGI3FrH/HaxFUdB1VFz+VwmuB2Q7O
-bt6RP5YscWzZMMjJGwaZWQmvX04iWCDM5bewUAXdDFKv0i8oIZe5jIk/J32/TjrN
-jX+wROSfOkHKIUQljn7KUWiZQTwDjP3y4Cq/PE/aNtJmcYqbxdyyK8KqXWGV7Yqn
-z7803ZY83X5+uitIQMF8mEfh9ikW4vfHZjm2k6uc6C27Wprh7Ufq9knPdZNNfMJZ
-JFJryXjOM3CDTKeM7gLtKbBvcdIFWenS8x5Nn7l2wfKJ616Q1aH3Izkihqd7uzH8
-z5i14ieySzMJ9bpKjDzUXhZGQwRu7yTFM0IgfTOIdEPoKcEq+aou3NaAVU3z99Uq
-bm2Y6YfsAIZb+DKrgi9DrpG5YCxzGGhl+EdFDy6BqsmGkJyy0dDUEAzCCtlGdvmp
-IbI0NDewWsGI7yqyKyb5OJjW6+nr2Qp7iobWFUeSh2aGoxJVBJWk4MA3sYNlwGwQ
-XUyxrpDpNHY5ZJHlhEzIXRwtkgFaAlDRFe6QiX8it16g6Gvxhu9WpmdjW9Gncahn
-M1iRVbhKU0yLOjfYxoGFPdv0qKLbEdo2DsIZliJ+Wf/hEfqO3PhVTJGiofK7V8n1
-D4Ev+F0TcatCUuFJBvzlV5eS74JET6+qZK1Es5KkSNPQjWEWdB4EHIevHxkCtqIy
-CyKLKcSoZNLE0rjPNapcShVpqeqFsfJPIlTmaIZuJNvXtWz76th6mLNEylrqhGXm
-bjlbxrDU3jFrgZyD4YdPWG1tK51ElcXDsRTmjavKiKWiCaVsupxvW2oJWSg8PSyl
-Tx4+m7LxVEcF+GzRY61Sw5sCeuFygiuIqQIUPx+f2xYY7bEWoXXO5owbURVstUpn
-vYQhq1yIAilgLSpfHV9p0BY8waBNWkgZvjtnefhbCvdbYm648smNwxBlphxYdvOt
-lp/VFcjw5RXlV+fWQnPA5SVKC3oureD5k80NstSeWHSy58UiSry6kvCglXVMuBU6
-dkMovC+Wwcp+F6tL5HfC5NISH41bwBP3jFk0XZEnj/CLuP1JGZNWxnzLtlz8XGfP
-1VD8O/Ca1UB7e1NgRgE243yxOkeZx8VHBinmsmWflWVM8RNzJ63O+nvclld4eoxQ
-apWwfkSPn/PJ9V3l/S+p8j4ssyVJTxCb8dRezhQ91fT6MaxvEBWjtoYcwx81x8g0
-/FErjRMUX5o0Hx5MxtuNnPFeK05UHSNvrZGo47DR1PHu7iFO9O31ehNKwONDjX2J
-FwtcVeQgXPGHI9XRtKMRV6SErjvWRw5qwl9ztzXWoRzRoL1WBjDhyHkiywQPLJ+Y
-kHu2OnQfrXx8Uzh8nz4cTajmSSNBkzhTOt7bO8QQO0wajL09UcEe3CPaNgp8AvhQ
-7KVD0ZT6XDoQFDLxodhrjSPkBKdmUErIxC6DVKyNWuMoiv4Ys5/v+OVfHL9kccWf
-F+uQx8YrU6JstUgBa5aXYEJcllc2yyviy3zX6vW2JO48wvoI832FPIOoFIHVjccQ
-RGh4EoIoN14rhGuLx4r+1Dqiey29qSFitA7JjxTs97wR2WvJgdvIWNze9qoUTMEI
-jyMtjjhlxuxxwZ+ONWqOHx5SXXHyITwCgRhGqXvd8CgUYWb4JkG+ammabglv9jVF
-i3SRifttdlImS842uo8St/lQBMjf0uOLPtG+8C8v/u9fODu3x40F/6JaWu3c8Wwf
-186JPw+Dv/w/rmNhL8C1Qf/iL//3RcbCcIapZPbH93eAfOMR+0DkFCFW4ls/6CX6
-67IDmQfAcqbqTsbKMTXJ5GJGtmlFPCfFnFj8ciAeHYwNxcYKUg4UwyjvBZuogGHq
-5rhoE0qN+whxo7dWE8zd6Ei5UnZ5VbDhTuamf0JsrHra2ICLNUqz1d7vHLx89fqN
-srO1VqpVrUbKVyNfJ8m1HdFdYtzHN8BZZ208nc2dxbW79Mjqn4y6jUMnKOUxOskI
-jw0caag8dzpS13gdqIWADkRLG5YPQbbTYpjvKJMnd90vsSVE7JiQ25Ve/scPD3zp
-s+dyy4tMFTWL27tNsLAyq906dJ5YX4QeP1tT47P0pItUrKHQaB2GRfPYcHc3ba8F
-trBiaFJ3e6NwrGl+bAJrscMsGFljwxtZY1iFRLs3DaJ6afhJ12geuj+acS3u7q7m
-xAWYI3fMy2BPrBj4Ta0dgz+emvhPsf70ufWnY4Sqz069UFh/BvB0kDHsDJ9l2GlV
-hz6tItX+AMNO9L/MpLM0Ytv3+EnfwJ7Ll+25SGrPxW8vJd+q3OFKDhUDyeREUtI8
-y6+bUBGCazuhFmR8eIkhCDGEXQvyU+DElgHMu2mC8s0jZ6vEl6j+rsKlPYk9BlSj
-aMjkfhNTPYiV8QEihN3pFWnTK9FHZKS9ZqUvBS4grf5eMNkwczoYCViWWlnfb5/8
-JwZQcHkABTcJoOACo8dj+ruFg859fij/1b90SP3p42HIyZ8cf9wvMrSOYGiBEGke
-mj/6hyajC0emzMaaUvxxYqy+YfxxR9N4ZAVSMHwpv+ZAktvkpUY5qfSOy+LA7EWL
-0Eol32Me/qEBE55/ZlvlZzYaKYm6Txn/Ts+s3OLTF0/pjQrJpC3IvIJJGwS3y1p3
-Vhj0rLj3VGH4NU28qtrci58gCOaxL0PryNZt2YbTEoadJYId/1EPKKHLqId7bljj
-OgGdkDslQlN1vqvIajclUdEpmoZyoqjEn4INhqQemhmeYRguujFEMWDsszTWR76a
-dfrMLSKEjjXSdB9NDG5zslIt0GNP1Rteu4JsYUXCbUnBzDSnwlM0tEyoplm9rk4a
-Pp4aeDt2eEqAMfDSOkGF1geyAnEm94arKulWU9IA7DMlI5VpxkgF9OBbXLOlOu2g
-zBKi4H8nyFtlyP7vHnGmlbY5V2oJgSc8ITzJtKMAVWVIWd3A1IoyeIQ0rf6eGloG
-22jSac5wJMibD8hk6/Q72fqfSLZanGy1ErLVKpCq1vNJVfdfmlRd/a8lVd0/iFSt
-pk+la7gEaA64fEsa5T6kEj0Wkb3JZ31JSV5BDlPqNy1NxbmDzZMOMj+Sa895PPmd
-tUNpz6i94t7r11Ue3/18vO6cx6SvrxcKerxO9zur8S/HaoSVrEaWPnomvyFJDDO0
-JA+HwZgLPxEgiuszOM9r5D3K8NP1Psqe61ijDfASdDZVifaT0UyQ2PaDHvODnp3x
-BjvtU5cEEUNwSqbZSkyrS6OSeRFDFJdhYxdTXAuy2ydJTZ0ZlXA3WRxWr6vZBEOY
-v6cp2tZSABfJpXBUJ5cCKdtL4Zb3auY9UwaP21dRBOAHkZ0jnTi2OHup5lMU15H4
-OLKCkiMUlNnXy1b1PiPj1PssF0Mj5GRi4q5KJMYVxHu2pKxX0DznUl5EHkrmf7wq
-U/lvwrxk/GUVXB5LXrLKv8GdjMKnvBtVlizzCKtvzSPQjHtQo9xaWTgOe5qxchG4
-0lY5Ad1mqpwFesxSOQ/9SBz5kozPDiD/1DIqI8c/UkAxZPzWDDJowWK4BD61FC4P
-Mf9I5iebOqe5v8LSuTrzo4bOhazCzhnRCkf5JZSbdDh6/HAU/k484eukbHXE7vVk
-tziMVU1DRShVi6qYlaVuyR5n2ALCxWACDl62AMtntMgiJW3rBwj94uazFxk45lQZ
-yw7pMdFKS4w9SkI0Kr27FbitlJk5RIyhOUS+oYw4lq5xg62xghzjxX//V7D78F/B
-7v95MUOm8eK/R3u74+bdqLn3xtybjnf/zwsHBcaL/25ORs0Wfw3ZKxk1917xd8uI
-g8Yh14hZXUMipYGc5Zg3MSmq1ylaFaED7E7r9fRvMRtLRVPDfXhYPTy8i0dAicdp
-7gSKpmrILlqaUcKttdDcGJh03liad2gtHh0PzcrsaBtdk+KGR25VLUrlDTfSTV7e
-7ji62c4Oo3mkbuUsBLVUArEUlk4KP6jTMcAZ49wi9awEMH1ShqzUSmpJYXxxBCaZ
-tqBFNcPwI8nKl7Aab8AglXevhLASYdvOpkfJk6rp+BAbNyrVjuiuoug0Yh0TFpM7
-hY41uTW3vstyMfp75ZoWVh2kKLETsqBBcUBVnJLHDw9hnHZkqbgRuI6F1baGvKO2
-/lrTzeQr0XdxVO4fMonNhBxkogCFyEKu0UQrY6eFpuyPbew0K+JtlBugeZIgapJu
-RR8Rw0m8SxixeTRyDYoCAwuRBjCmSfZbKZr8nnUoed+GIbMeHryf2JLyfmw+PEzr
-dbzn/mSYaf6ThBea8RBEt9LcnrPBDA3J6e0JymNyz6B7Kt6zklGfHq1VD5ks0dU0
-3YPFklZ4Lgne4jhRyK7X/aOJijVdlfodSNmu5HYiz2DNhFjGqdgIOVx/ZBmY4Tq2
-LONhCLUSE2GR5BoY5fpINbTizQki1YJ6plrS5jzoRLUSSUFaY72uFkA1FCTY2Viq
-VHt4aKIbFbi7lbGzQxouNm2Gb0xDnRrK0rz71XQoiFS1o7m6VElDpEFWqukmsg2F
-+qbjsn3DAI9YOXGKbmvoqmGZnoXdjO/hOLpvWK9bLjb9uJmhBovbNyzDMeL5idBV
-Y+qGwbwE36U9Pgr0c3WmalqErqJI9qLnqW9Y6nfTw29revh8K32fD5tZ6TaSTcuf
-5ziS/Ec4jiQNSmYzN+OlOhFIrrCH7YcH0nA8ij36q2+uVnDvnl85HhIbx8LzI5Vk
-XBYeg6MEfYckrih4SqShVN55AVWrmqbncp8SwDTcpaKQiLMunbhmaK/70Br1nh2I
-QKdhj77zzSX+hJfkxnQhG6vXp2qx7SjT09JaWyjtQLO0xZHWoHPsqWX363hgeKlZ
-hyUDaNp2LnQ89U0vcFhh2LMVJCEMho3g65T4S8UwhCPH2Ny+XlepCsNUMv6tSENe
-HMKyNGR9rl52HqKdVnmnQeANs2F4jYnpn7NHRFKPhqVD2IoQ+S6t/uOMWZ/pStCC
-TfTO8bEtnIDQeIK/1hJGoIrYvxOP2wv+neIVwb2jiSURI5/tZqv36X0jxSKbPd7u
-mrKr0iMpgYtZGN+qwK3+qjInIaWMexTuZOLX0kr2HIt4NfY+Mf29uWPjvWCpCLf6
-AiSu1c8mu7y/ik4S8Z40xpGGvqbTexx/7N1yBKKAs5ZsdJ48hjFolDEdSWWK5ndi
-51sTOxbXGXtqZ7/DlftmrNl/3fo6zT6/T/OdFPqfJoWeQpachyvGmgu65PeRHpEW
-PeOU/X6y/jkn62Nuf3/PCRoTyGJWn3Y48hg2FSBBxlsm8WzTXx/zmxzyme2duCTA
-+RMw4It5b0ls01WQ41GiKxNir5Xqw9VsDBj0CYEFXzjEMkUmh1j0zKMwW4rF61Ii
-tgacRw007wNng3Xl7s5lpLCClo5tu1hXqB9i5dmnctyU3LEMlAmQDXPHtrEHJMmT
-z2qt/Lh2v/FxjSifrC4OLN8BXbAhkt764ADvZ2za2E8SgVAK4lfQtxi0cew5S5Ni
-W8x5Nk/27R0hNH2LfU7TzJqJvS18t2H8d7BhvOE2jDeJDSN7arfh5g177OwfQIAR
-/vwKAox4aqetoalI0zRk88dOU9PQXDy3NA2txTMrbiae92Ui6ub55pHLeOvEEk7Q
-6h1VDRqNN4yXOY4KR5B8PEWajkd0bHgIR5IA/Q+gzWT5+r8oOSaJ8L+TI88jRxiC
-OH/0mvUkuQt9+y3vGp9sMYqrJGkkXaUgLWKPhOl5xnp1tSUg0CQXtOf29xD0XmNu
-eraLz8Gxr4ypnanqNSz5yIopMq8xh3fuKPiQ4eAcZMNyHXhhAEc7Io5Hw3aClWuu
-389JIADrdU/4FHa8mTjfUifDP+G9dvNICvBSGMn7YpF8felfW+ePrE4AeV6lLV6p
-PDLGtlGJosM4Xm12IaRxinw89XEwZ0sspNj+YPo0UImWhkUpb0ca3mTbEs1Iwqqt
-NhNfmnHrhP/jkpZRmaQvfq8uvUT/kZrnnYiKG5TEfoUgAKpapTXxiI0Z+WkYxnkE
-rj14m01BhcUEFzc9jft1QXh8ToMePa05S3OlYvRYI3YM4/wI8/ss0BZ21KJnckyF
-xVqUiHMQRcQulnY0ul8x0jAWz8dxoxuMS2nAmckKYSWqytwMBCtTEXvls7d8VjtL
-heiVTa1uHS+nvIHPlr8m/ElGBFuCJxAxShYOEuaw+YXztBDpEneUtYRO7l+OFCvH
-to3Z0VXkjPKjzTgjRoY+uQGkYcaxwuVRKdZkZfmWKKq2np23M1WU9Mpx3XCPY0ll
-HDHSXQzkFpvcZw+dVMne3oxNqTJGmf5y7+QnSa+X6n2EpJKcQDgwV8bI48qcpKEa
-8lP2E90ZV2hgbMOZ3PNwXNUfuVBKPgrTPuhGhKgWoevSxrpkRqChkxm41JAWBNz6
-XLs4cfQHATnuI/3xRZ9bD492JZ6zCWev2axpwi9azgfVxLSuZz4JPVv3IuRoWxal
-s5wp6D7wLZ0i06W6ooB67qJ0HMAEMuMrumQ4zNWqb0GkAniGdGHZ07MdSnzkJoO2
-MnDDsdHUKLiR8779Uog3VjpsLnJsfYWoOeFW4speiwuCts4Zd3epoenR42CepnvI
-eaTA7UjBXK0YMvC3FMInsaIUc7UCPZQyRmya/UhDwZaygpXpbS8MwyyyNgVI+f/+
-X0VDDlsyZ6VLJg7ZDouGuMTPrpjHZnnV4HIjdM+v1ioQ0VxWtz2OASAHzHqiSUP4
-jmIvAKtoz/R9cqugjD6vesfIMV4slt/ySRAo6Nax6VxX2h0FzYGI5c/QZ917eJin
-5RHivvfxGjbapnTUEnHrBb6jMHY5ASyMYgrF+E4fwqw7yziXk76LPIEEwXK48kae
-Zjaybfj1uoPmBuOtv/1WnIIoTxkXjpYswN6emI4xsh8e5hqaahFy0bx6+ebXS6o9
-9ZBrTrCrU0bpPb2AICnAEQX4MG+LP4sJTTgeTg6ehTRwbFy8K4iFdQZ4FbVC38ce
-vYAUxrBx8s52gqUTBMeCDIyQx1F6v2uoTTRLp0yBWbhStGfyS49R6yK2H6vz4cEi
-XkBc3Lg1fU9V+tPamoR+DWquzc0AJDAw5OxDjd+lq5m2XTO9muPd8GBDNeJh7szw
-N4isAhl+q0FFtSnxa2arta6tQn9FAhw0nkwcFz10JDvFB3+iidQb3HTwkzFgYC4J
-zAmcbTQ74OB1g9xgf+qS259Bsg/uN9JdN2dvDJ2ktNcsSQLkeQMxVylBE4M2AmeD
-0a1BGxzhoBODNgANoXP2dWVajjdDVwZtLMnEcfG70HUDy8fYQwPRFNdcp3Vds/xc
-m5AmLgyaQSu99F1061SCYGhlyO+pSgjsWE4RuT5koFi+7v/YBUOKRko8vQpSpMlV
-UOLxLJ5YBiBPq4KU7KQCrBg+9pyZ0CSBTScE9KFEQQqbSgUpfCIVpMA0snQ+iQpS
-8lMoqpUnkOXLTZ+CFGny0rek6dLEca9u6bTJ7wl8ZsqUsYb6IoQVxyPorVHwh3pb
-r9+LI/E2Qif1+j0/K0/SGDslooKbSupqLZ3AHiX6TYRAdqA++Xyq4BP49Ztx9dnv
-pjUTrxdY5grrQb2+ksiRQfQNWbVYIVh9TgqIvb1pujDG6EpD1zGN+za9HijMtIoH
-yWNtJuozWl3Oau0pu5MxspGKjfsILVVcCpTbSGM01Sphld3zXWUv3iBjdF4Nmh+c
-Krhki49RoLHTV8QCsx3TJbM43BfvpdD5ijQ4dlxsv10runPUF05aultJ7bPqtTCv
-nHCgZvf2PMLR0hjtOFpK2K4EvTmLtG1cxwW6h+y6wxigfqRt4y7uOCfja8hDi3q9
-9/AwrNePK3fnBt1LGEdfoAzG0XtIwjj6KcpgHH2I8oYGxyiDcfQPEfc0mdNzL+TL
-w7xv0pVfYmMkIfX8p2wNec88uSZWfxYtzl3OlbtbyCuPVNXH8mLjpZq7/YyyOyj/
-NV1vhdqyx1TVd1hdhW+AhosD42xw3mWUOlKCpem67EDDthMuFaQIUwrlLnkQT2Mt
-ZqUKZfMTpFglxwZbak1Kzp+nZQMpH64lbcidtQWICC1yjpzkxaD4eBa6Jr/GKq2/
-9IhV0lneaeZndqfFBzjuWaE/O60IXcvbYjLb5nUKuWRGtrulupBLE2Ke4rAkcp7S
-TxUDdZXxSGYR79y38tuUJXdxQHPpXFfUYxyMnWLQEci0FMYZnHAG3WZZUyouQvdT
-r0ThAhFnk6DabGU/PKjU+Gvfq9E5rk1DGvoY1X5jX36rifpqwETUbh3XrU1wjds5
-1fQamKYESTpnObBdczx29tbM2o8fiE9Nt/bip0btwl/XKBFAnBmC/Jy9YfUZv7GC
-f/urhkYY0XFU1QdhBONM1YLgoF7fwVm2RLtXaZFow5qWBSvKIMQojShS8oOTg/yN
-j4DwQD8hoWeznrK5cLxZzeQBRGuqxQ4xlkK8GuAbVEuTOL2iodrKxWaAa2GAa79l
-mvgbMHx0blIlviEcR9VgJ4W60A570jqTzgzUy27U7L5F2dHpoXvZ5Ei/QrJBkj5A
-krWSvkGSJZN+gUrtnfRzVDSc0q9R3sBKvwO7q9ikq4dyxk9XKGccNUBZ26kNylpW
-XaAqC6xzlDHUKiHQY/bdJTNVSUFrTlAzazZe+dhixdYS4QCCKZOqB0MWbNpKtXrj
-AqIa5kzIntQYAfyk5vDReUJzNpnmZMzcrssM4u6KRnfpBdx7Jdy7cYLQdN11YuiX
-T9rb25ubwXxvb2IG+GVn72BPQUoIdwkAGi4VlMNg3yc+AMHTNqi9vVvT9+C+QSGp
-Ih9E/eENZk8VUKwMAGIPFTAT17SuAQieqkqaO5R3GZ4qoFami9/7eA2A8UsFbOC4
-N5gPEH+sgIvltQAZv1SV6Zo0bUDyVlXy3PQtYkqlSwkVeTaObxE+pvyxAm7qY8+a
-fzCDAGDT1wp4m9gz7L91Qz7I6WtVTy0HexZOMkjvVXMTYp+ST45F+Owkr1Urc4l9
-0+VrTDxXQC5N17SS9ZG8VUBTfGcGn0jAoZO36jmauE4QTw97roBkJ/YHx+NLOX6p
-GguyxDPf9EzRZum9qo/E25i8f+ypslyfmrO4THiugDQ3oc/h4KmqVuyKxQZP1Tt4
-g8980xM1S++VM+bNiJgtb0YqV8xyde14UsmZlKqVbPrXH7Dv3DretStWcyapsjZ/
-5caogz9XQII/EyeYfwAoyJBNqsJh2PHt9yCH0DOvVTvAdZ1VIBZf/FI1oo6dAZfe
-S3NYiRwjEX9UQyVqdD2fsjWX0LjqBRX2o3lSLbde9WVrKULBpBcUSo/0UXjgKaZt
-zRnL6fSiXG5Lrj3Ouem5hO15BNes51O25+Jcr55L2J7nrpDp7im5SrI9IZ9s+aKX
-m6o8LXds0qJv+VhaVmrUoqfPT5i/RAKpV3x4wsyUlZH5sLUMc7WSMpqrVQW0pLvX
-M69b4B1Oa6QvT9h1idZWr/iwtYzYJkfPp2zfuy4/z3Ni0m0jn0gC9GLa43WlIli9
-4sP22nOSbr3qyxb6f29vSSYSE7Akk63QYHFOpQw8YWseGwfXUg72+hRMmBG569u+
-bh+l0lIeyR2sHE9X2N+Sr1GEvntL/8/2lt7Zf534S2+3/4P8pSfGRXTt4sQQIZV1
-ZtMNRcgk5NvGBSBwwGe0XyH7u2v2p7tm5xrYv+O1nfc0jtniPyE2NgxjWq+nzlO4
-tlkFY1uevWgClPMAzlZwtU1Q3l34d4fgf4JD8KcYSmUN/WeYviWhZzve7ARuyHzC
-FlU1YfLz063j2eS24XhefLGmXlfFNRS4+s+vD7wl9tpYqZmiNVSE+5ku3TxcY2Wy
-dTMkNtY0lLn4zRdlvZ7AFy9fXPNFnrnSIBb+112kKPRLWDUU0tWyDlZlYB1XH+td
-6ZWNJ3XweS7ay23j5RP8f8ABu2QflVo3pVCPGpBkvNhIGKzSlDeQjR+ENlZY6vsa
-oqWX3O3t8va0HD19/hOpxBJPqnkkWwiBLzs95Q5qGxBPnxKfTXcSp1krLZGvkdEY
-EUaP+cZOK7mocEj9dUL4mSgw8ChX/ljVDndUYqimETQ8fEdVTWvYxMOwUBqrMJir
-Jnd2qiFGoHjinIXz4JBVqR1KEbBZExwDR1PHM113DZHLd0i9zvYia3v6pGoJkDNV
-fXG2OAlJCGuSaoelZ07fA41EzaQUL1e0RknNxvxcCH1c84i3Bz2cuCntoWjCE8/z
-/Q0yClOriP1foGCLSSKomVO6ueOw+PGDw4bQZLMYlM1iiCyDls+iY6ihYWVn8ZAV
-x6tyjZBPJFtmbiPwrXrdbbBh499XBiSiqcFTD2XPo3i0GmsW8ajjhfhQ9QwvwTkZ
-hfJoOgbYOPKCx559Q/lN2V3tKr/VnEBW1JmeDWbAQA0vnZnPU0NKliZ1GM5aI9ky
-GPTByu6UleSRWyXCboBr0J1pEjmOPavewwN3rNreMQxbrFmJfhHrSNR5Bqq82m9T
-77e4KjGHIw/fcgVxbRnMxg3hpXduENVGbe3QM+ajJuvhfNQa8+ZkbZ5FDVBGjcdT
-YIPACCBYwoj/1ISbPgcHNdPHtd8C3/oN1X5jE8F+p95vjdolCWsrMwCn9a52KAiD
-85/Pfr3q9j586p0cX/TPhle/Hn8a9ofvz+t1v15Xs83pisF3iKfXlF0fPFOFrqtF
-6SY22QoM8pvYqdetZBNbpZvYFAMcpJv44QFHqodSZ8Z+xSFCkaNFUcbXdwaxg95Q
-V35owj8FgYZQV354B/8UFCsCWdLBu5fvXimIa/x05Yfuy+7rrqmgWLGnKz+8OXjz
-5k1XQYn6Tld+OOi+bL08UJCsodOVH/bb+y/33ymIq+JY+a13r1iVqb5NV344aXdP
-WGKqVNOVH9pvXvXetRUkKc5YF96+bHVfKijVjunKD53uSe/kQEFCC8bqPTjpvXyt
-oETXxbK+nnQ6bQUlGi0YgePewTto9sR1Aj4mbVZtrKBiSd2TtydvFSQpoWCk2t12
-V0GgbmID1W0eNA8YFKiV2Di1Xr5hRYECSVd+aL07fv2upSBQFUG5rzovWwqS1EEs
-9eRll00SKH6gQW9ettkkyaodSH/1rvVWQVndja788PLN685Jj2UAHY2u/PDq3cu3
-vZ6CskoYXfnhbafzpvdKQammhY1ms9t73VOibbSCvNAyJ/9OhRRFUKeAQw3JcwdN
-XF8jkkoaICKKBnuH+6qlI2+sEg0FhjhQDwOZL8ZHH3yydALMqFbi3mBVVFXiP9RX
-FQ+st7GW3TAgh4CrTliLNN1RTTgGjoSTeEVXPOIvTVdB8aGebntHzpv2zuGHlYhq
-gEVUg7g8L2mtIIUoYhVyikgKA8BLBnAgZqiW8/tfWVAr0iJ23sC5ph35qgfCI69h
-+jNNJ4C9IpiYK8e7Idc4d8rGmAjf1sQAp0PpIJPPXGAAEY+R6c8g0iY0BcJssubq
-JmK1c5PfQ3JEDALNMQJd9QxiBMiHysAhWxkPnSDOmHFjb+J416ISV/P8gK/XxUFv
-BmvP6ovTnpWSUvqjMpCxUe50A2yLUiYB+lBCzMjDKS+1TEwBNqOPZ06XVCa3GIFH
-s4t1BktS+Aahxh8pYkKe8V0q8pVSEfRv4P1Rpv99Cb+b0kYRPm/Avx978h9xheOp
-JuNXTWl9y1Ig7l3EKFUYcHbemap4RMdsNSVighEdx/ye5H5foA/Pxv6pucY+3Psu
-rxaET0ZetuIEkI5tRuTlSzPyCY2J49lQqVYAVqvqliQ8RlG0k+bfaYlCpTa14mqW
-hOJEisNeJBmVkNKALxJVAsk1aOp44HjcKAskkruLjo8SEdA/Q+yvz7GL2W7iLksy
-xcrjlRPzUGNHzQukf2rW60mYglQA3RxrDw/y62F2KOKjgkuqHI+SeHWw5w/EEaHq
-8klGLhdKADKjmZ5E7C2JBKjixlx1wJ5WS3PKc6JJ6byueJjz7dU0tKUKCCfGzlTu
-TYS/wMX8EudQDw9bW1Q2PyUHIL+wY0YqlkW3TrlWwy/gAz/BB/hRfOAjrCFfatQM
-U1iuJ7yjxnafWPFo+Fu6VeacKC6qXqej5piPWoT8bI8TTixSPbVTFtBCOGZS9zuM
-PWweltPMvPbd3cQLBlGxtlsWrum7z+g/P0AG+JhuNfnwBeU0sSygSgY12CK5/Oaq
-vEBD/y7+ooPHNYPBo07zvpOWX6twC/Kel4Ov8EyAbwy1iUzAxty2UVO5W27wdKch
-Ks6YIAFQS46jVOmTwhUq9Tjv7xlO0Xka8dy16km8d8QdcMErtDCQWkjBA9NXeSQr
-dAPfaKUO2Ko94JX0f8eQDh1xYD91xB5zDQlHVjTWUBCpWlQhc09CL4obQIqLp1RB
-ioUZCaQgxYc79uPGlPg905qreVE8KcWpo+a4QclnuPFnBljVduNYay0tUj3tkI7Y
-jL81fWWXSCx2ilG3TaOHnkSHOo947bFNb4Z9Egbu+hzTPmiFLwan+v3V1ZwuXYb+
-4aY81djRTkdK3NwAYgGABCDA9JRYpnzpZ2sfOLDGyoxQ2Qlfokzjw3yvNF6YvqK3
-mi8RPDYWAfGSd8tkj6/4Y/JJvF/1ztnb6+QtAeBJAXt8wx+TT+L96uSLordazeQt
-BuBJNqu31eKPySf+jtljmz8mn8T7VbfH3vaTtwQAkrDLHjv8MfnE3+HxgD8mn/g7
-YY8v+WPyib+zPrZe8cfkk3i/Ojljb6+TtwQgToIBbL1J3hIASJqyeWk3+WP8ib87
-lD22+GPyCd4XbOjabf6YfIL3a9aR9j5/TD7Buzdhjx3+mHzi72zQ2gf8Mfkk3q+G
-p+ztZfKWAEDSCvK+4o/JJ/4OXXjNH5NP4v3q7Sf29iZ5SwAgyWcd2W/yx/hT/H71
-iQ37fit5SwB4Usge2/wx+STerz59Zm/7yVsCAEnBNXvs8Mfkk3i/Ov87eztI3hIA
-nvRP9viSPyafxPvVMRvG/VfJWwLAk27Y42v+mHyCd8oWyf4b/ph8gvfw+urzsaK3
-Os3kLQbgSZs5e2zxx+STeL86GbK3dvKWAMRJF7+yt/3kLQHYj2Qxe3IeOHLMTFUO
-OOqkQGSEx4dAytLdlhYrYSWVoCBeGVdbWwJxXfursot3lb8qiTK6YREbG8rgrPv5
-tHc1PLu4enf2edhVUldKNPIZJxCUMHqC6GFfVaIxJk+Imw0HpZyWj/yGYxudzqtH
-+Cmv4atJ8BVlhf0AIkcjP3l58e708/nPCnLSlE+9ny+7n44vegoy09QPx5/PewoK
-pJTep/P++YWCQint86f3PQVZcmnv++cXvU8Kco29FloZWwTahRCuOVV2mfvZJIKr
-Xs4JbakOvHfG9KthGEn6Tvyc0rpHcdv0pEI0/dc3+033gs0XCGMzScPGk3B2yI0k
-p+p9hLxkc2TC4xqSkv9ICT3O0tqKvlKxptXr8nLFWpGiItq9ciVWgrJjGKRep6yV
-BrSzXlf9xNwo0pCfbsq5LMIA9a7rBJQLLcAsClS8Uppv4EYS3C54eBiNwQEe25MU
-vI012WJWdtVE3Aamlh98PHXujqRnnTDKjjHqAdjKEt+cYRQaOy2wogywzzjKDS5b
-izjS18gy7iPksj8rYzRGU1BCIZs7FpA6CCweG9lVbIEQ84EiXGmf0as3pqtONcRa
-rfKi+HbGxqoRzJ0pZYyJwdCEHVqS9kqOUuA1HJaAtQhZIzzWDpMxoPV6lutkXIk7
-wmMjZDgyYUFiOwHM0SCr7G4v3uGcFP3A34hj6zUAq8VD5XizGvgRBk2N3OOU94MV
-5JasIBzHcTUMgzW+XhfGI6yVkYZsA9iLPsVL1USh6oIBLmv2TNO4lVC6qmasuKbY
-HfchsDUZtPGE9cwWawmxvqN69fpeC6IqxuZ3WHt4oCyVjbSUqkUQDtcakTFbh7AT
-IOtKstyr11fcwoqwrcEmnpsEq1OD9TdeG3PkQLgMho7cMJjLXBPDJYdsmuPxPtTm
-arLR7YeHvFJZiyTd7lpa2H87PxsKXx3OlH3IjWniIDa7A71n7jhf2nGOoWKOp9AT
-t96NZEcyE0vCK1GQO2wOYtW7xzYqyZAH2TO4dEl6bItQsek+MX6yaueBXga2nqMy
-8kKD2Ux3FicaGF8WlQYmgZGHQPKZUV9mDfr5kD1zuBOJcBxqFAYMTbRM3BG2YVhF
-t/9Oh91J0YgOBuSGISniHSVPuotIutDSw447Pv+ELeJZjov9I1svpMG24wIi4mMb
-xEQPDzO04hgfwqavjZ1mwcmdi2zetpnhPjzcR+jGmDXiYxJN/sfMfGdolJ7WY7CQ
-sxsgBTSMAPbNmvVp9fCgrgy2ejV0Ex9abkVweLvh4/na9mFsKr7PnIBiv2iAlzlm
-9FiImZRXI+yFZ47N5lKxZo1wnzSCShVOZhq1i7kT1CzTq83N1Qp7NWcKYKYVW99N
-MDuwIPj+GtsigxPUTK8Wevhu5bLJBmtDywxw4o6GsMJMVkIQYjBevBUOgUDkiWsk
-ZM0DVBtCU5QUFSeDoMLO1JClFkx7qHav4oYwGZS3nyS0zyN0rEVcRFgsS5oYXin4
-P98OIaxQKZiyPBkU3TIKk6oTZGvoPl5g+n28BT2UZLZ5rJBIXnlpXHtjp4lYTUHo
-UnUJ66+86Jsou3h9TRpoyL1ixyscmOqTSzE12M2xWWmS7sDWSILnQ2ETqRxIuEH3
-ci+bkRaXfo3XhkDWfLOfGKIp54bdWJlrl5g2ujJ2GBlBjoh6jlx0grCmnxzKVV49
-pcqIDe1Osmsp4CIgKO+M6lGIXXKms2zX66t6fWfNhpHTUeqdhu4iEXbIU1ttDV39
-L+L17v6djr9BFa939zW83tU34vV2SiZNKLNwvb6Tv/nw9LZFcJxpRwkzqcMTdJY9
-ITjochzmdQZxFg73Ignw8DBAjK4QNy7OGxZZThwPfwIi0A+4BJyN88W/01o5EyRx
-4eKJ1NIm8sTFSRzzqof0Ryy32RtRNvY0vToZV8YLnvqEYWwYn41xz887f62PxmhC
-CA0oXA0H/C/7Vo9vSD3ZcOZIftE3iEpfW+NDYalKAXdzc9WapYuWXsA9BSQ3Lr64
-eabiRpysoRFsgzFD4VCCo/MZS2ES2ozy85wYFWVJYYODFaiTPNTSUKEpJDtMbCcQ
-MRaRlhjKJvMrTXAvq3ShQHG6hgeWDSsjXc7AxgMtq6mL+AAnDezNTc/CvnbIGFJ/
-houGTaPxYVE/xAOkh4ifuFm1IedssRZFGoppFvB6r0VInMvPqsX/ilpWZhhk+lIo
-1Yw07lxymtEIrvJwFgL7YEYUSdegBQLmiJcDOkgc57qHsO/rBDLS6FCq2tfQKvPm
-sjM2VUM35HVQr6uuqiHX2GlpscKztmoILLy1cwGKaU59mhJguh3xweElqBpapSjz
-lKNMFZaQJg6WElMWbqlBtQqiVFg2C6k0TTgfaUeniQnLVkzSgecg7ICpqooCjUV+
-2gbAJyh3ui3NVVkQNWDE+x4FwroxdVxGspcdaz+xIw3/RCKtERBfkg5kDp09GmmH
-sSTCeUSKh0feGJZuaqWV740jiewKIOKeoCziGcocZgHFtktRbFtGse2xDuITr0Qe
-6+XltodZlUssN9shDw8gIiOyiOzhYUfd8dkXRr9nhGdCfOdInk+lcdpxVE+r1/ER
-hlSdRoiEMmIogNIjHglfx1EUeQ1bpSjWXoizPeMDIY6HEWkoC3ySpQfKMl0XMgG+
-LQPtpaAcMw8451cGe5qHvYjlcGXQwxQ6K7woA57li07lvGXgc6mD7Kx4pPRlCv73
-3uXVh0+9d/1/lAGSFFAorIowfgojqbCKcE4KJ5RaRRhTgonVXEWoQILiiq8iTCi3
-KlaFFcGsFKzbe3f8+fTi6hdW8dmwDNqNtAjIj7+8ePFDLSChb+GBuVo53uzzp1PD
-Ipv13sT0G0vHaywChs3+/wAAAP//gs0rNxFJBgA=
+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
+KcH4DS6lrdVxdBle7vernA9mXDTGaj1e3qWKyp7ABHNUlWdUo6zVZoicWdCM0Hgb
+6sfcwnwjOd6+XeaK5jaWF5y5hWNly1uJPp8tJBTMFSJKIw6Z5ce0Tsev1yuDNfUa
+fETYq1V08H4/N+fPQY5Kawz2sjaPFI/1XpOrnQj7ffFbf5LlSS9NN0+xXFqhTxfk
+m856YXE+S9CUim7kNpaiR+N8XSwSCi+20Hq8HjWbYqBAVz9YNmAWtDMrEFbPJZep
+oX3UDQ1ySfUKhR5E6+v63K8eikYXE+UiHmDkm/Y4h9tMKMQ0uowcKF/emzylRlVx
+p3emuHZE0/kpfXfcZYyTD6lVjFPjvOrVsh6zCksGw86iYI8z3HNQon+MLiWOuJeK
+dMK4TBIbHElr5YFnAYL5sVYTaM1ppiG3/sSYf4KyHuT6jEuFh/SxDshaYrw8rM/u
+nrKXSkWPrk+MHLtbqDx2t1A8drfQdFj93PknVp65uHb94srlJwEe8fdIoVbaesvV
+DBFJNRdISQtrDKlcjYJC2UhsB63zpksASqy9RFRnnTqpTy/yWXMeEx9tm2otHClA
+5GpHRXpC5olRnlgvb3N7r3wYdq2LlEeOec00lBOagSNyYuiohQ85mmuTyMxc/PLl
+45wbViM/WGnLU+Z7qkhHUJbYVV7a+erdI3r17uRJBYan9OLdw3pL9uSZdO0uPbO6
+d6nS5VYoK5co4V3Lnl1IwKXKVL5VTgcW7QT8t6qUEvc9hANrKIs9f9JOwLmxNAiY
+tkSKcxMIUIlk7eeqE1JpPp07N64Y8R0ISvwJlOwIQs5PTtDvP5SAZ6vSKAvu2Wer
+CRBfZQO+9KUJDX0iDoIvKbe4U3Y9ilsRZ5bKdfx8CXjyyQlrgFiYAMWyn3yyOj2W
+DXpqLD+eojGLBMueemoCaTqVbHvXqdp1zhOlYC1XRZcXFh3+2MLiMv+8+JWAbre6
+Gq/eTZnbGy/rmMQcSXJ7vUmynqaT5UVjy1tFHiW+LC+KJpSXpZPlrY4dO0pn0iQE
+AY7SfPMLjYbIuVpdyZGZdcXj8ldkkuPky1XJQ5V8DffQrjw51Y4Qt2xgOsIk/fK9
+5LET8N+PwwyRT7QDCaK2x3aHSpYUXOeDUpKeRPb5a+vr16Jrq815exnlh23+/Np6
+v/m5+Q4wTdspvL92Tb3LHaxDpfVw6ZCWekSjxxrL5pzpmLMmoG62So8EVNPPn2lk
+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
+cTi/zpJZ6zOeYmvgKbvpcJYlMzxhR2Dwa+XnJYvXqxvLJblJzqNpWMs2u0zi8OVc
++SsAtWz/vgjnULUd0PovZv+LLgTFTXwjYw7TcMXy+yKCK/1eQGBMy+d/6N7IotTY
+LY2b23bRSQQ5ZJTPARrk7jLKwmk0z1qnDe09ukEaw9ls3jhbkpG+gzkL03k0zzrJ
+zXkUh7/qu0dzu7kgz2ZAw+Jq0ty2XzrLh08saGFFLrKbI4Iw1Pr9aDyehndDgJen
+S0vNZNYpzxx+xUVGwzZZfx0ld19TOvkgib7qc5wNs/CF47KVI5XSKd7zu43pXoo+
+DUK7lTVT9DWVGb1Y+FJL20nT3k2duyi7PLjP0mHxGnA7MS5Wpl9o6jrMf/KJEiVq
+HVl/GkNzTMP+Y9V56YboSgHlJZ/PkzA7zMK1zwKstUpxxSzW16AgI94LtpdgvKzg
+MczXtZjQh1yS34tBTDBKAq40vEluwz9XrSpvXrPyIuif6yZp23+KKTa6m93ebszx
+YzWidCuxt86TSvFKUGt9M14oLlw5Ql/Ct4rvakTfK+rWKgus5Dtt2p+XL/FY+KqR
+m9uNdZ7fwaIpra32C2+x7xlRrSR/td+2n570QqhVAMpnLYvpUNbWUafhGYnbDVCZ
+9zu5RrPwvRsrC+dZfjEUmSQmDQTZpGJp9IlhMFK87vX38inUZmbn1+1Ps7NWtMyd
+eJSSlZaykZqcnf5Fg9/N/+D1+V2QWLd4hTxfqr/R0+O4yfx8kV4/7c18apMp0ov5
+wrbJDL+59G2bjPFbUGnb5CL/VrZNLvU3C2ybTPQ3p7ZNHlYMi5s/ZFjcvjhN2no+
+L/p2GwL/Y6Zg5gQsSyaTadhNh3f1u97Q3gRXFsN8eftoFsbheHt7BfwGrPDC5irj
+xojwt2genU/D3XB7O8mnA0msywJ7KgHVg6ZP83MtAy5pL0lRO71w/B+4rbG9bYa0
+l0yzDXq3Ylw66NeRBCy1xXw4CU/S4eg6TEnazmrEyJ8V20rtakJbtsggj1ZKa+gG
+dNmQgy1tEm9vx/r62Gkjgzoc3OKuTaPYWEn3GqNpMg8brUYyC+MGaWgcjbM6dc1K
+t7bSGnXzHaHn5C3qm09sutoTdzjeNTGvRra2oO9I4ugZYi+8WIsZmYFk7dDJdsPC
+yfdR3MeZV3XrOpq/XZxPo9EeTBaNaaA263MPAs3G+SLLkrhB8mlVEUQxx/skMBuB
+ycjOeRZb5fcincAcNok702h03aoLA8ETOzswjWvkszmcs+TwbJElaTScNlo4ldnR
+c8YGTE82VHI+G0IV11TqEi/LNJYkaza0HDRs2yDir9Hk8kUqNp+RkFS0s9ElShrG
+4R0+hlOudb9M1HE5nftc45PWCt+QCnMrJkncSyZHC0hVyLsGaKbQyz2xU8zsSc5j
+7c81Qcx9lNTEgdR5mJG6xthixBRVjeE5czIyD4fp6PL1MC3Kwt0qq5tGt7lT11F5
+Jx5v9Bd0XH5fnvorl6dGBfRf0XTaTxZx9n2b4dtvM/yVWwwo3M7z/f9qsyFb3QCo
+DU+FQGbL8s78f8ISf8l33Wi8ie2ii2aTklGtbahoonhiN21jxWmEjx5pHWQ3G5dZ
+Npu3fvhhFt1F13hoYjRNFmNnNGoQn2wxssXsXcxWCFxYZv48nM260U0Yg3I4HLfw
+nmuurV4P0wa5DIdpdh4OsxYeUqqTtKYMQ/2gqLl020EHUF+xgEuyyjMKjiS1G5gE
+PWGOkvjtMLskabt8N+8kyqbh6oC+cWy8ZOtHxgywWI1XTTB0qtEy3JnfNFqNhv3C
+cBvdTDaOtpgfr2An5C4aZ5ethuANMpxmrUZD211/bhhHxEuYjm3On6VJPGkQfVjI
+tlf65cUeIbmP7Mo8rUkOriYao+Yze5VE7axumhPtvKg+JJIFAFfGTjJatYbHJpc8
+tMcwqoO9R270N5ot5FYHNL+R8/a4nAKQuzZYGSuGy9gwXDrtsWG4kD5m1vYEOW6P
+ncU8TPUBn2I74IucNo5u1/ce6MFZmL5kwW3MO0ribBjFmPvh6Sl3YFnYv02b3NaA
+mhZN+w+UtNi5mIb3OxNQ/ksy39uU86K02vS5F/xLbmrFY780bXL3sgE4qwzA29zI
+itBWTub51lDNXIYYPN8Tb2+vU8TmVA79euLCSTTXkF4yHEfxpJXkZl0vmmdhHKZr
+DpicN8N1k0xcLC0t0Q6pG61GfQu7tTRV+y9L/GVFh5pSHdUM1IQk8Qnib3259QyM
+YW3IpkubLDYXPqkKX0P6vClL2ybHm3FMSxzHtl3uuNVX3BdOlg7j+RTP+9kw2uHB
+qjgcZfaakyefc1FvNSl5MBze2eiBMrzIGjYpNMDaNOhzUCfS0rA2lfZS2LBJZZJX
+6UqQ3URv2s3bdevT5cOPyrN3k2biHL9KnDekoW3WBvmsN5ZacZO5Hi65b8SQv7ot
+/dzrWqA30Zgr80U1V9lksdYn/ohMyYyMyUU73F44b8gl/v5MJvh7TB7w9y25wd/X
+5LZ9uZe0JnvJaXb29NSEn/bnpd1qasDnpW3Y9ufty720leqkaZ6U3LXPqzRPT81z
+89WhpY1vJI2sKLYut7ebcTuzSWzP2s3mtL11sb19a6yk3J6Ozuy921Zsn47OyLh9
+s7093Zs3ZySxWw9r19tne/Nm4WwWF57IzG7NyO329rB5S0ZkRqCZ721yfjo622rP
+trej5jkZkbFNHra37wpgE77aM3u5mzgjmDimZOG8aTOycH5uc7JwjtuSLJy3bZ8s
+nNdt5pKF86+2gJj3bReifm0z7htv9y1eYpDiVXW3eArVxUXTtYu1u5lz0Y6bXNrr
+3Uy2VovJH14kWTtqZmSL2iRpxjZJ7crLvTXME1cTCnxuYBJmjSi24qenxjz/zGeU
+xmxyfzQK5/Mk1U6nyxfpt8rlxWpBOt7ebmpnlnr+sn5js6ALFy+8JbmFj0muVias
+vRSplzSriqz1xViVsIVU3d6GX2WvcWfsba3vEjx8zmw9eNqkMWyQz+ud1XrLpe0M
+X5J1LnJeCOzSXyWJ2kkztbe3k2Za17CbCFS6LV9J3wzt1ufln6B5sRBtPOGZv0sV
+kxQ9Ya8TxyZY7cXzakDZpJm248JVdokoXe80G3MjnxxdfCHz1n+s+Gc83RnG/8is
+URLfhmmW85GVJdYsjW6iLLoNLc3T9vJr3DEbfsnMdY8m2w7tlfWOJgdYtR7SlBDW
+hnn2UseVY0SgVYiieoxQwJfzdNSAkaLUjAVRyKLdbDRezW1nPptGWbNRRDTsXRxv
+nCiez8JRdpws0tHa9Y95Qc8laW568pvM88Fo3Y5svIvvNDVj0oiHN2HDfnpKywDM
+UwiojK12G7RHkXSYpxpi5F6j8Qp+WwvnKoniZvmwuA250V+rVjutOX4UoTSnYquZ
++5UHOCmgtr20q8GkGvUqIj33F7amfWA16feuTodnT0/zaj/k5UHfdTeJoqnV9VjZ
+brcN5/L5AkqcL5qw1uoqRWzYh9VjJisHM+vb+s/Sk6TIIdblMN6mM/OQdM0W4/NF
+k9qKydd5PF+/Fhq+OESUVfjCGPHsxVvdQcUL5p6XD9uenxtmXqANMyXALqsdJDL6
+dGvx9PRsrNFz7s9LksGfOD8d0LRJ0m4Mz0fj8GJyGV1dT2/iZPbv6Twrd/nD0/is
+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
+6358M4qPXo9nH1+/S9+cHN3146NJ9OrX2UfzUufp8c10OtZ/+Qw7etxrH9wedQ5N
+8v8r+19H7QP/4+LFTfThLn9zcnR1fPreOT6dHh7FFNb97Rfj/NX71tHNr+bHD87n
+j6/exkev3y3OPjj3H29ai/NTPR6//uXyPOnnZ7+9m/6rrS+OO5NJ97S3+NfJ0W47
+PpjgOkavXupR+8X1m5Nf+r2ridPtvL3vXh3cHnfOFsenZ5O390f28cmt3lvYRv90
+Yvbve4ujDobZ98enZ3qvM8r7nbfz3lXvrteZOMcnB4vjzvX8uDNa9DsHd93OW717
+9f62d39g968mk9POkdM/se96VyPj+PQ673dG8/7pgdnrvDf78YtO7+ra6F6d3R6f
+vr3rLW71/sK2jjuH9/37iXOEy8YEZvRPR3b/vjfpXV2b3c5bS6T5lOXrndhGr3Ng
+9E579tFhD/+W9zsH8+PT97f9zui2Fx8sjk/fz/tXB/f90+v7buftbffqyDrGZe7f
+Tygth4v+/XuH8KBt3/Y6Z7f90zPz6PB2rZ09QgNvJ+Ub5tGBcdwZ5b37s3n//sjq
+35/pfcojAjs+fY95cdtvcxjhx23/9PD+uP2iV9cnH+IX/d79gb7ZV73bfnu9r3q3
+vYVt9jo94/i0t95X971Ob947PbL6p9dObV8tbLt/f6T3Ood1fWV1r3pOr/Pe7tf1
+1WKjr6zavlrU9dWopq9G8979tdnvHFg1fWV1ryZW7+rtbW+zr9baud5XnEfXeu+0
+t95X973O2/W+YrC1vqrpE9JXlE/68enI7J3c3h+3bee4c2j28Vincjk/7kxu+533
+WI4c3K5e563ev7+m8n11eNe7mtCyJ/aif3V237s/0o/oWDL7pweL3j2Wncn8+HRy
+1796e9ePsexc33avJkW9/di+xeOu1zlkPD6Y9+6Leo3u1ej+uHPm9E8JP2+7Vz27
+f394f4zLntiYzrve6dE9rrfXxnJxZvZOcb3v571Ob9E/fWv2Tki9eAwvevc9G9fb
+i229f39mHJ+O7nl7e6cHVv/0SO92eovu1dFd//T6tt+ZsPZOinp7sb3onfZue/eH
+d1Sm7Puy3qN5vzMy+6fXVm9B+L/A45XX2z+xb3v3R0a/c3Z3dNi773WO8Fjn9Rrd
+qyOnd390f9wZTWjZs4LP/RPb6neO7N7pIfvt0Oh1jigvKny8ZXL51unfn2E+2t2r
+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
+ih1l3AZsIVE/3+TwbqZExRNnUiTsL/I3nqr7i6jRiAs3eVy7v5gwV2LK9xc5W1dK
+ogZ8+avoIC1DTJC6K0vybv6IxemaTIh8/4nVaaZgC7z6ZvJjtqzFlwE+t8Z9kwuo
+9b9jjerrP9ao3+ca1be5cHr/2TVqOSocPirc/3+tUWkLfqxR/z9eo5ai3FIVGaXv
+ZzOqlWVRL6SPFGwxUXQtJoktpp9d84mpQNQsKMQ6lGnLTEHqflw+Tw7yMNlPBvow
+QNroMsoOkKKTq1f2U3JJN3sjXlYDxO50NoruygdwqKi789VjjW8Z9aSW2bKQq5oy
+6L0YB8l+FiQAT7/J8zDbh0HKiq6+TMGVtDQNINSEnunksacmep7t60G2i1SgJGHy
+PMMVquTXZDckEUjoebKvB0kTPX/+XAf431AXrsPnAf17u7vps2xPjVkA6y4qovgf
+9Ym1rPVetp+c6CHuRKjWeaGfkGFI7iBHuEu3jCl58Pvv87Gv60389+LiYiiDlEJ1
+i0J1y734/ff5BTRJ8gKaOGnqY5I0dVImC2WCyBoNKKJzASHW6P+zWU8Uysp+IBYb
+Q5f8Pr64GKoP5ooqXrHk+cXFkABGFVRzgkreTXflpbyb7cqqvCvvy2BEi19AHdI/
+F8N9eXe+q7CaTV0fk4KDGEQgH7IRsJTVXVmtLSmr/5RVMGX1DWJc5b4MUlwcJFUE
+MpiFzP7MdmVlP6SkLeXd6e4IyBP5ia7nduxMXS4Hw3+DZ4yvUkNULIP//lLI5Qsh
+XzjsFNfpq3LbqHYTa++xeBmI27+GUErpsyZioFM2pGexWJCREB9My5Lm4vat8EqM
+xihxE3QjCqom/indFv+UVuKf9nDpFcurrlR6b1VUs/nGFmSFAwHktRtt0Wx2NCbL
+s3kW71VWiqVXCS/SHmbR6DqawACtgmQF5uHDChv0Zd9vnA+IldIPeBNl10rVvqfh
+ZeVOW5H3Notmynpowd6eyuO1yP3+IQ31obFbkh4Us8BauwELCbLAvJBNPLORYlZA
+wjm0HCZEBZKcLRrGxXc+s5A8Bw216Dybz1AZv7NFnJD6ECnqfqLlECmZSgmhsSVI
+EeJ02Tpcoitr6b9H6Y02jW5mES0RzWb/zaNq2WocjjVZVVcqI74VFMN7nbQdg+Ux
+9IDEqsFkLAfCkbl0pmBNzt7uxCi3x3xvGVUk8nwallz9XgXg73YgaV9l2QUV+fhf
+Mn1Xu3K1faI+7BjYAFkuiR1SHGmR+9EN7KfoZTpPxod3I8huZdqHyo5BBENdfWv5
+sP6tXb8nqPqpOAWMQHmoYP7tp5rN8wqiZfSw2mhNxk8qJPT8ZDqICxMrajQirJXn
+U4S/xhGCzU6EoJakt4r6DC2XCs4ePtA8AcQocK6gzLVSAc7D0Kz+DbPry+gaHsxm
+eTfOUXVandNjHPTONmwIYoCrq7id5LeWr+JJC387LfHQ8Pyr7kUchWtUVCPa0V4R
+tkFPa9JhB7U0OZijyzSL7+mpqc2h/iXXr0WzWXMa56h5kWbn9HTvCqRPXzA3ihCc
+pNkikNv0K4a5NkrvFzI4n86zbIEZvBVRXCKaRv8ve2/a1TbSJgx/f38F6HmOb+lQ
+OLIxnSBazXGwQ9w3kgM2nQDD5JGlsi1bljxaMDbov7+nNqm0GUgnPT3T+ZBg1b5e
+e13XCDqKcOpt1jsd376HArBNzx34poLW+Aifgdc182nqhV7At3Mgy9/QzqnnOIip
+zDTU+IaGBqHn44iCiWJvV8402kSworJVg1v25AwoIcifAMWPJSnOup/zs+7nzB8g
+pf8E/UWA3QB+BxE9f+FcsfkL08xkuimjtULyNPJH3JEl6jnnRaf6bD/bxra61KML
+9TtYVcoQwCPWBQvTMFwGyps36ObVbU8A5HW3InwdOYY7FwD2rEGP4Wc4CuwQHUQc
+wFMIpjZ0LGHb0ROmB3QwoSgskx1InSd6zzlPzNbj3SaCR2O5VNxt3dv199gBCngM
+pxAtpQ8nkWP4AmBvR31ALlq2G+pPBd2qZy6EsUUuuy1iSOeoNfq8mliLP9Zm07kf
+zWRbG7RWPfu9M1ro9zdnTnSzke0//rg8Ox9O7E+b1r9plJED4/OlbHRkW+9MV/A0
+EzlE1tz3rZ79vml8/uPgYnHU+jTorXqd9kTvTCZ6p2f3Pt44pqsvR83WUW/WjbRB
+bwLPGsHI1Y56i6lsfWz/cr4+OrAOzMjaaNHo4Hf3fNNbaZ029pbcs1mUk2VrdOZE
+xrZoJ8P5YX9wRMqt06givYEc9rqWM1r8sb7+cnlvzrzJVTN0rDPd63UuWuez3uTf
+nYsDbdM7+PegHfbOsuO6Xhx5N58by+vPh7NR83I5WpjRdfMoPD/Q/ZsvlzPjtB2e
+D7Gn50mv8yAbXy6Dm+HhYtR8mN986U20Tu/d+cHl0jp7cBLv+2eXjtnU9i4Ofneu
+v1w6N6fvD4wvl17vA2uz9e68Scqwedyc/bEwNyT9xuXS1++XNx3Z1jYXK81uTM2P
+7fDy4+9La3EVng8a4c3nw8b550vnZvGhMfp4Yfc+6rK5OPJvhrI9WhxFN4PexDy4
+XI+aoXP+JY0Sw6K7fBr8Ho2ah86fiPbyoHUuIq3TRvu6Oj9th9rQbOCoFyjtdG6z
+daFr6PbOnDnq9/rLdXj95f3KTPezrNxsdLA8PP98uTa+3KBxyubiQ2Q2b+7NhXzU
+c8nYRmcf5JvBpNXH0Thw30Gv023q6feSRruZFP6lfbF9DTV8vrfMu9NtpnNcTbRh
+N1kDLupN6b9PH393rg8uJsbni6Oeg35fTkcLK7gZyM10X3qzi9nvXU2+OUP3BN89
++/3hp0Fv07P5ezuxe2dTx/hseRY+J3O79/F3VF7uzVrvzg9wX8+Mh48W0Q60Qeuw
+PzQ3/WH3oNfVVueddtTvzGVtdr3WN71GD0dLaa+1zcVG31wF2mn74Xw2P9Q7V01t
+eNE477Qnw073EK2PPrzY9DuozPuONmvjaBxapy3rp6tVr9N7OJ9db/RZb63NJoF2
+2mpqm+u1Nuu1NByRpBfpne5aG17J2mD1cD67eNBm3YbeaeMoBprdavQ7ZkvvXB2e
+40gDk4N+56LRH/YmF5ve5nymNfWN2dA33UCzWxt9Zh7oQ3PVP22v9dNWqz80V2hO
+5x1tos2u0f7J/eFFU7dXm153JeOoHp3JodaZN1GZi81F83x23dQ6E1nb9AJt3Zb7
+pyv5fKbJ2qzd0DdXhxjmdK4nw+RvD58TvTOX9dl1QCIDXKD1PNBnFw3NXjV7HTJW
+bWMe6JteoNvpOuin7dw8zXRNOjiSxDpdl26gr9OyGu6rG+kzba3NLtb9waqVrkm7
+1ev0Vuez9qG+uW7oMy3oD9oPfTznK1nbTBrnnTnax6g/nMv68PpB71wF/cH7jobX
+rnfYH1419M0c1VuddyZob2VteLHWhvOJdroikW9m16t+R5sMO7lz9cGz6Z0b3HzW
+5evPh+7o7CrU173JzcIJRh3Z7m26h7r8+9ml3dv7dHq0uv5y6WVgCX+GT4/ckjzi
+nd8uL0d/vzs/0Js3m1bec/9/L/bd9L9UY19yy/+x2Hc5+vzBvfmi/cS+p/JDv4h9
+D7479v3y3hsdXN6b696E9r8YHfwefhr8TrHxw9Q6u/K04XUrixWv5cqx8Lf3zCTY
+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
+AA==
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /js/cozy-client.min.js
-Size: 281959
+Size: 266593
-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
-rIiX6lC8MG23q2WiIYCVTF9vOYGtmvmCavVIrSyZaCXK8N3Zxen7099O5qdvX5++
-PX3/z1H9g/KAQmw73Toj7RlwKiZ4MGF0KztYYjBoRpHDCwtuVHojUOeYbE6t1I34
-C7sDTiah5lz1JE+1KpKpVWEsS80hagoYntmCkG7NPbQ+AP23Z9rQooim5pUZ2K8i
-GJJaLZ47WUJHsKC2y+Pk2WKc2DW7ottpgrvM31MZrDQ7tTINhP4xkoXUMv7mh4/X
-sh7+ooSBUw2xaXh+U24s7aU6WoiY1Ika8CgdarUvUuuVGz+Ho6HZtk0oITfBiHKt
-xPKoz4MaN/2Vh8qv5tz3j5VfDT9YHSweBnJNVYKXTz4feiBwpcB7Xhmv5qovYGSt
-JvKaIoOOxzJK2/aFKJIzI42ZE8tLs0u8jlFeZWs6SYDTaZClAWgZ3HwWKXE/lM/4
-biefV77iXgWl5oeuhkZZWSdVzNJay3SoxRvlildTPNH02KzcqNHPifcFHWOuzoPk
-DmkZXYVoNvkF8VYkie6rcY0EiMWiYDKKAZ956fCg5gX7NBiEufeo6SSB+rRafBPD
-uuq4hCfEk8DdaV0XQLatc7o6xDE8kP4NnqYnkr5SG7RGO5JGtV3uDVXtjqPxl4V3
-dB4OFdkAHGRFHfgBNf8JenVQNM5D11N0XU9FQnMMHVzB2+QaYwMy6tHuwUD6KkZQ
-4pHarLvdqKFWrRQdxsxN+iLebhea0GN0VCE5oPTQqfWRntZnS/UTFHTb2mR6/VZx
-e7pO3CmbERsGpjsf7ssZ8cKd7V9kGJgI5e06d1+Y2XWcunnOiRHj/Ig1fjibctz4
-XNL43NiYnI+1Vsmq7TKueNxwQQ2CqUokUCn7mvk622rzTO6KYuykucts5+msjila
-YFtt3dTv06RzlBc4yt0zsJiR7q+s9BRvaCOMEy7HcSMu0Ib2NwQS02za9aXNZLpS
-7Yimq5lW1O1bffrD3bVMscSMwPxANnZ3nPjjErq23YE3dnMS+UN5V3Vh7rZnttuF
-7VtKvadwJvTukvaKKNFXRLFarkm1GB0N/lBXFh7Snt1k7HaeaG1U4NPx32unqW+p
-EByxPeTO477H9VMNdf7kAJ9XaFrmKUelDqQmTSA1I7qP1VhlntZHM+M5ZIRAhpKQ
-IKW1UdHkviW+c9JSPlX0wR4V+f7YreU430PFZeXQf83uhsX2Usvh4U9KxlFd0Ouv
-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
-bOqrs5d4V35+8tv85dnb129OX77H6/TTt7+9eHP6an76Cu/CbfnTV3SJxS9Ozn87
-wewNyOHbs/fzs3cnb5HR+/D2L2/P/vHt/OT8/Owc+bZfXryavzj/E3J2tuLzk79+
-OLl4j5zcXz+cnP/z/N2L84sT89Yc5PDV2cs5ln3x/vTsLb00FdkXb813X7ydn/3y
-Dycv39MT9dIvc9NWeg1y+I8XfzU1noEcvnn1i3n6DHL4+uz8l9NXr07e0he1dv1G
-36vc0zcn85N/Or14f0E/eiNw8f7DL8i7nrrKLrzXP5y/oZ8cA1uZCVwxznKbohjQ
-c1ZsBC9YF2P5vwKAuksriQKDjqo/GLQ1PDoH2aPWq7+sxGXjHZXUMN7qDk5gVPqk
-AQIxsmb/zmLFBPxnw8s7yd7oSwFjJvMh4/InDyW4kcY89RtG26hdEls+dF+XSRW7
-07ZJ284gsqPqxSEgd+yNw1kb4ZRHbHjLLq8zeeEldgZQNCzjFZPvLMOn8ZqyRWiU
-grKOU8BpLfzEQdsr7veYDwbXQosenFB6IRrWESZAIeQatHa3228biWjWLXxEFDoO
-GUGjuUERNgCKmzPzKpbeYpHi9OLMBltGD3nPyzk2I9XfeolsjPYZqjFG+qk8Xyuu
-ehkXZ7fcMunWy4QTe4djm9m1GzIlHKm+ZKTj+jGpZreCVdqI2h0VQmK0FJCCJ6yn
-WsLS3lrk6ELPeyoVlY4YJM4zvONNezZHQvyvSXIvdShOs3rUqzntCrQwlVUoQ8QF
-QXM/gbvtRHSBRaCho3axShrGtSYMtY5AbWP2xQSREo2JO0gC2WDQ0ZQMbfgGgzz0
-jTVVhWVZAw3pMB10hpCgBKmaZ4t/rVpzMFMiiCLphfUyqzypPcTYIN5kStLU+D4z
-c9tdWTDV0WPF7KAbW+6CkkyrGmbj2lMl8nmAIM1mjAUV1n2AT6ZGfAY+i6ZBsU0S
-VhQB5DMCBxojCGT4Dd8dPq1bSIYda1hJjPNkJQqW2u13IoY5U5vNt592LFhW9HRx
-A2qvazCBW/5AJe4Na3Zdt9JcYTgPq1yRcXH9acu22i47Tu8msr6PouYKl2qF596L
-cZq+jwvPhDYj99lEhBmJZJhP2cwz/zSBTkgDyd1e9AZHrGa0sg9V2rM+MXbJ80KK
-nFHfYPjOnG1+PsaeAtYMOsoI+QJqMVYSpylGmKhBoO/1Kbi4W1+KVY1pcHm/xpvu
-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
-3wAAAP//gj6OC2dNBAA=
+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
+8fjmeIZ6FMhcGa7a5p9bQlUG4LxVmdHnm5jekJUfr1av01wQSngDNrQ6h/BX11f6
+Xo345DYVQKZ8H98Sn5LP/1T37yWMVkAKAV3Ti1erF5Ijsn3M2wnAM2PykNt91dsn
+ci97MGxJLEScbFQDj6sIXeEF7n7yVd0Xt6kQhDu3wUj+719lZlS5hICNzqpbuLMU
+rGsftdzTCbQmb0GWFgVo1FgjG0UZ9HCq2wEUwlld0xwNk4CEe79yry7Kq1tFg1+5
+i1+5xq+aMCTxcTH8RrIk1detwy5cM5aRuEHYrji5ZYoJM7+i7vu8+608JXfAk8KG
+h7zVtUoDsJfmvRXZcpLEgqx6MV31PqdZJsUE2eAdWckjFvfWhXrmuCNcKQ+xde8t
+K5LNt994EHkbIbb6mlY36uzYleWGnCu+Q4xF1POmqOEoRbHa6FT9PwkmfYztvX3N
+CqRwFuNdWWrxP5ZrcIcSTEGsaY4Vs3oc7IrtSs5QMpGc3EVFCWeJf5WusECJqogL
+xME1IChB6q7eRU/XrVkQf1uIQ+Wfaqvq3gLVG/E5uXNZRG7mddHHmNt5abpjuQW9
+dHKImqBQfyWlsdjr0Ip8XUJk8q+78os6P+nKv6/zV135d3U+6cq/rfNvuvLzOn/T
+lX9lHpg/SxFxAtEnTH0KPkP0QiZMIXqDAQXhKUQUhGMI0XtV4A1EP2EKRhcQ/YKB
+TPlJlphAiJ6pAr9A9FzWPB/J9HEAIfqgMp7DmRnPums87/3YjOhn9ApbScpBF4Jp
+hge9w4Zf0+yLgrsMQPizZDJIlpOepMOKVLw3qD8n4pUgt8C72sojdJVsSPLpShWp
+EGoI0c+432/Uu/lyPYciywGUzwAEW9TEuRBtnYk41Ac3BRjEnbc/1nxfhrtYNi8P
+qIOyF2KpwDq2x05SThBj73OcipTeePK4Gg65wGvA0cLLxX1GPGSVvK5WLMk95Gky
+c6sleU9KelmqhH1vnWaCcInCWHKVrmTSXUo+e8jLU8mQIe/ngvD7q23M41uZe53S
+mN97S7njiaK5OSigLwVj/ek1Xk/k/vz8lPuqtcGgL2kUTYjk/QYDYNKxKoV4RcYl
+c1uaRtntNiOieU6qJcDqFvg9gPrhoB+aWkY/QHJR6taoSQzVyhq+R3KJsuLssAxm
+moqqLWSwLBtbrfF5527DnZBovtXiYABa5PpYYzUdRwR1jB2tiFySXkdWc4yUiXR9
+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
+ma1CP6fEbXwZ0TlfHHF8gLk0YlhzFpQ71SRVgY95cCj9ff2nBqJDyaLhlp3hvolP
+iyH6bL0pPhziR6K6Ktcvez/9Mla5fgkQnh4bz6MSRrjI6NHYyTzLb1+9fvkOe/pV
+546wkju52841xWaD5tJ8YkZKgt0Baq3zoPvfl1wteZnp45EojBcngcx+RII8MURI
+zScLwqmaT+sIHYaGpynicN1B7Z/TFG3ADIkcUvr9EYIvvXUfNtXzNWF6j17BBMLt
+gH2QhIPbmN3qhmTE+iiFPS1MkiyZJaOPSOGHFx5Ymn1i1Y24G533XU3r5xf+Wfuy
+p6KL0xVBJa54j0h/qhNRide/rsSHG1wXu4w55g0XV5VZ9/BjrNim0KzMT4ip4JIC
+OQYbAKUXg4qpG6aCp0rNjEYRcs4/Yw6aHKrvU/U5s7CMOnf7n6jqVfkrKrr6T98R
+gfF4TL9g1MXh0MfAuQn4Vm5KpqILRyvjWjxeMWhxaAPv3F1jgCUj1GHkxkyU1V+5
+vgROZ9Z532X9DOeH3ZVyPSQv22ZKs09MwJYpOJukqGZm1CvKrgu+SYjjA6y9BJdQ
+xDjKnZCIRdhHL7I9TGr7U0hMyA1T51U2h/2+sI42VTbXi/qqNVEhzsny/D45klWI
+PuDKFCdLOZr/Tt4+7wESwfQyS8JPs97isYVBGMMgEF5mCTcrUh+7duYe802YQz0y
+RVLyhpesHGg5sIzwoBhAbbBfG7bmb+JD97deVbqBVbQ14IWN/dCaKGDcBLFTpD/J
+tjW2qSvRrw117NmT7/5f6xIv/1s69KFeP59zdEFAldiv9e6T37cZuk4Rz341QYUi
+PuN4e94Cl/jPcaIP1vor+dH3DV6IVy+4okktJoO2O9q1YKUS0cGPsZND3gpB5zwN
+km1xwea9zRV4lCz6TyIIRxfFK7D3z2k8X6/+C/YAXH5FwnkXFqHln6fAkLl+UOyG
+gAG2hhdg3a5t8hJ2VYtHjreUIsBiGGp+ybdVtndK2SqzG0UQw6GZ5J3Qmb8/Oxr+
+2H+XtaHJfBEwdTjciEXB6d7GTNFpWf/hRXC0V+Cf8/mw/3PVH3W2kkqjfrSguBDQ
+MwPgBjNrplAM6fZ7w5UHlQTSAfBLIYF/k131+7fP3v1x+eLV2+WrF1SP3755894/
+uVtTM6w//v9Xrv8XXLm+/v/Ulauz+C+C8X/QCoJNf29QNLDmr2Oh0XWPxT+8KHtf
+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
+iNjw2pmyJfDmMk1VG5ApTVFBCw+9/KdYj4MxKdK05tQNH0aaI7PEZAMCE28dk5YV
+/ptGGxua4hzo1C7ea1UrnjrgQd0woV9YHz+wcqm03P6o5La4KCwGHrntZTE8V7GO
+xaJTtP0WGrMmLQofZ98dm8T3xzlf0L28ygyRL7ON6bxiN9kGwE/JaxeqNR6bWCN2
+gZgdKFLYPbx2S45somWVN1oPuPmWbYJaSIiIu+Rl9KDYTW5Vua5fOC/jnhDzZING
+rlqhnk9wARXE5PXTftPI2TzXqtEIOOh4F7kbtQfWfr5+CHunh84IpzmCixRXZ+z/
+rZwOO0TvA63j2AKLtuKJ5teBSBFp9lTDELmX57eUuObxBfK2pBPC6Sdoai018p57
+mNoTeJIXT4O7cDEa4WF7bOSJsfG94fQlLIB9xT5mmgSuNJN2FWnTjmhlKMLDymie
+IJ+1EYFTRRwAAOJo3nYAr5x403+8Wstf1dp/7fspurd9yBgx0mKmj/kV9LAhO4hj
+QD5fknNyS67IS/KGvCMfyJ2PxPyMTsj7mjN59vR9/sxzJh/p3fzZIv8Y2BL4hQ8H
+ZN/Qdxp9JKJWDWPy0avQhu/SFL2jH+1N27uaCX5nu/CKDqfkLZ2QHyMAjcA7kdde
+x/zC5PuWetblfCPP31kni5m9fg13kvkfNLoj357EZAMOtGhyoCsRmwXEmha8X3f5
+3DSVqCJrsmlELmeGLrTzrvvy7lyU86q13qWbV0F2tJpXEeyAESPSVI932y1T2Mg5
+gnbl4h1xOchw4n++2bI4oqqREl8UurBWZqDfszGhJxbgVJYsao2VuJpVbeQtU9+4
++oYTnGsqSEWBiVzbPwAY+2yzAffSaCHy8OZP4DTSfFu0jruT4uVQxwMm0Rxoy4LM
+nbi5INqSHxh3UtLe4Jy2ISdiwNatTFP19TRNhyIvZ2hD914czXbH39pPnIkZi2Vu
+TZKtPaTrXKusmaXxLjp6+5QwJwdPz5CP32KHqilg40ygvf0icyH+M2nIv1k1p4cJ
+RxczqB6TBgnyBGu+yE/3K3KoW4sWKDsElOtTrQB7px/QbHY1QDM1Lxa0lZhB4v6K
+3WecWLVAIqRegs9EciT2jGPRGceIAuvvhptdg5KYjWpoT5rWS3bW3beaMDIUZDjF
+WY+yi2jQbwk4I1l/ObDV7aZkzUKi7Wrvm0+0JMqnTWXZieK1b0lQaHQ0RnGgiraa
+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
+16oMzS5HmqW6Kv6/AQAA//9gIn3cYREEAA==
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /js/cozy-client.min.js.map
@@ -35333,705 +35199,690 @@ AAA=
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /locales/de.po
-Size: 17899
+Size: 17331
-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
-5NPS60UAAA==
+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
+bXQ7Ofq/AAAA//8I34Bos0MAAA==
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /locales/en.po
-Size: 16326
+Size: 16199
-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
-zx79bwAAAP//UOGAqMY/AAA=
+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
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /locales/es.po
-Size: 18052
+Size: 17467
-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
+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
+AAA=
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /locales/fr.po
-Size: 19073
+Size: 18988
-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
-/OJX8JaJ8M8iDfb+OwAA//9CYZZzgUoAAA==
+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
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /locales/ja.po
-Size: 17948
+Size: 17766
-H4sIAAAAAAAC/7x8/VMbR5r/7/kr2k6lNqn6Bm++W1tbx97ereNsdnMXO5whdb9c
-1dYwasQEaUY3M4IlKVepZ3gRAgfMazCwIL+ALIFkAhdjwOZ/udaMpP/iqrtnpJ5X
-CSe1VVteG7qf5+mnn5fP8/QzeR8MqYKspQRdUbX+994Hn6pZWQF3JXEUpv4f+P+/
-/uR3770P7gnKSDYtgX+W6V/+mEwLUqpPVNL/4ixJa0kpAW7eJH/RdJX87eaXgqZ/
-3KHe35XKf8l0l5zMCkn48RAU0v3g34SMIEMNgg9HdT2j9d+6NTEx0acTqtII/BvZ
-fUtUvp28pUMhrd36zT/97re/ufWNcOsjD7F+8I1AfzCQyqpC6uPPFTWt9QM5Q/+p
-/eGT3wP21z/8+vdknXueIRVCcDuRlmRJ01VBl8Zh54iNarGxNONbPDCq6IrWWWTN
-bDa2d32Lvs6kFCEBE2BEVdLgjvLtZGAf/SE217DxApt5jOaxMYeNJ9g0sbmBzSNs
-XmJzDqMNjN7SP/08PhXEMZgA2Qxjkp4EaWVYSnHyN2fLVn4Goyo2n2BzCRvPsFlx
-OJlLhJNR67CM5jQ4KqgwASYkfRSkIW8CnmX3FJBS5CRUgUY3hC38UklKMrijwgSU
-dUlIaQCqqqJy6px+bhW2mBjNk1l779I2p629Y4wWWusrLbSG0VOM9jGaotJu4pyB
-DQOjmfpZzjrfx8YUNgqNrVNKYR+jRYz2MNk1hXNGR46v738JPpM0URmH6mScDOzy
-yPKfL4FfDf8JU6LCKxQbeYxmMFrBaOdGxGogC/yWDzRAiBsrOIditw8ImjahqAkw
-ClMZvxmiCrEDYg0X2HhNDmXMkx+iGjYfkZ+YNccejWVOO7GnazMckWCKMwYfxcht
-2qgyEbkLG8vNYqnx7Dxy+3BW1xXZR6W3PaNSgtNwa+fv4du+VOQkGISaJilytK0P
-ZofTks4f5AgbL6kvngT8QpFlKOpAGNGhClSoQR2o8L+zUNNhAuiSzns3NotUFxVs
-LGO02nhy3iw/5C/kxvXIe+3i5ns3MTIwKmO0i1GlMffayj8n/2xzJWGljM0TajbL
-LWJ+hXYEwTkDUEP0LCJ/kn/SwOMYWYkYru9y0QJZZlzQyJSn9r3QdjbQPNq3HhX6
-ARWRsWjLVOOErjavXtnmo85vnWBbwWYOo4p1XMBo0VqsNc03du6AMEWGe4ZNdoBN
-jF5TM696NhvLrrZjgwzT+n0oOnoPXKDfpKOoRpMMubQVEgyI7xYxqt0AsVx2SSrI
-oWbp2FqsYXPb1b8vHFB5+BxCksYGuSN0RnTDLzaWHWrO/c5j9IJGpXlsLNvH59hA
-QZ0BjHboHXfuzz4sNg4PMTrAaDPSkmnmU4SsPvrLKTeE9j9Qy23NGsdkmfEKmwfE
-f4hLzNKfXEVE6xXiS++mfXqiuAsA8TdA8r0kJ/134MlNPo31RM+r93dPRUMTChgR
-RF1R41K9Q984aUehXxJxBCQJT4su95iN10zgRPedQN7KofpVMfzA76TQBByXRAh0
-NavpgTOx8EwYnGBzFZvPHQsmfy7Xr4qtvUsma68MfBbh0C8Tn2m7CskzNOeQ83eS
-TP2iYL1dcDPGrBPMiLJq9fOF5j5qnO41yw+bpUuMFuxjg7gKgeQs82xhY6Uj5Ffy
-sCKoCWKj9xQdCKIujQskiQ55PYBdDhGIXo45g42n2Nyk+s4z4ayr6eY+8mWfHjjd
-GYXiGCAFluYLTYX6mytqrVXgGEeNUt0LkaITX1iObZv5FnVbA3hQhomwceCmbzdc
-RVHsIe9T8ajMVQaIqH/n3WReaeV+xOiq7Xa9aEWRdUHUQVbjraRMbblT32A0/68A
-o4L9cqN58YbaScFaW8RoylrKY2ORHD/U+glSzIyqggYd+PSXLhHKi2OYygyC0w2W
-GqZYfCUCxXAJYsg4PqGEJM2hNfTuKDKM3KdKYjISNYIPyT3TM38EOAjJWUYHuh38
-4yAk7RSw+ydx6OIHjB75Avf1kGUOtXKPG7vPaRH2xnWDp37QaV72iDtXiLTGnB93
-0rDZE/QMuyoWWT+lNU54PYLNx5THGUYVO3/hicseo5ThhM/07fWXjkFHZOkYSp/3
-WCAGNnb3C3vr1F5/6c8unytqUtFBxqn7Yh0LFayrH6jxBB31dlYfVVTpW+j3Kop8
-qrzFuE2dNRopmUmFYGd77qpZfhjG4XYmE/DdCLAIKHuS+RuHh/WzuWZumthdbr5+
-fu50U2jB5gKBTrgPYzzogLGwI85jY65989b0sb09F0birqLyYhNnJPD3f3P7Yavv
-pCQo6yBDrFbWBd1TXkfDHbv0orW5hNGCm1EPPIk0eKD7rPQNw6uoZh8WXZxAEQux
-hPZtlthR3WQyRaPclA8n9sfxHoBqWqKdA6DpgsrbcIdNrUcKKhQSipya9Pc5qAoe
-+hFFV1ITqqTDIK2S9WzOJjD32kShnOARN1VdJ461Y3is9Q1OyiJHxBGFpgC0hFGl
-fla0119zmOfAyr9orJZYnKUpvtwOsrFXMwhTI6HXwUj3gw+0uO3MesMJtHJPG/9T
-tKbz3YgNKClJnATE/qEsetJ1uwis1t9cNVZL9vpr+2SNgKX1J44yzR0aE16xfNEs
-H2Ej59SHaKHb/TmsU5I85gPaK2HL/yyNQ5CJtOYWOrNmz1myAr3sH4OT3pAcHRH9
-Wz1mRjNxdC3ticw91NU5xMypub/YOJ3CqEB7rSeU/guaPJcchfPKRxXr7Yrbki05
-4b3y1g26mxE2Tw9G4n3U4Qh6iT4fC/8LzhuCUWHoitaBjtjABd7WzLT7q1CFBDLU
-L6YTEiqtxXXr7Yavf/HuKkpATfQlig8/0D4imbj+tmjlnhEssvSoflaggGmLct2l
-HZFKV3UGEkKYsYTWcuHBxo9ceoUBbKMbbbi3KhpNQ9OpIIswFc1qftla4vLwn1RV
-Uf3JvrF6gtFGs3TCHcyBDNgokesmN7vQ2DxvrO56Ki3++hjpL2QdqrKQAoNQHYcq
-CGVIrInYSMmDEeII3IWaJiS9JIKFsP1jnub3A/JzY959MTlwkHfjAFEfYFeNqO3u
-MShlTZsOKkabVqFsFbYoJtjwtYaCwmo6uQAgKzoYUbJyInjUFU5C6m7mHDYPWWvC
-OvrB2i7xMK0HDgFdOH0dc5cSPWiWn1Ht7vLMrDdPrMtFbxNoN65Mqb/ZtvNL9bMj
-4gveOq7TYvKnz8AReyxo2FnDyntrbbFVXMA51DwpW2uLtLAPFPM1P6V7CklVOgQZ
-QRXSUIdcU5D9gtQCxLCLrsPXrKvp1l7eDyzb9ESa+f8qJcJodn55bboqTEgqFPW/
-ZlUpjLTn99emrolKJlwL9BfvIG1S0nSowoSjED7y1JzMQAzghNTlxnJj86K18GNP
-vbCOzCz6Rag66CCiohIFeTTZq/4WXAG5BhnBWL5lpfpZrjl7Gu+o40JKSrybFPbR
-U0p70ReBo5loGUXWINAnMx78SJ2OJGTabCOVzTP6+n9tDtQ+uBQxVbQKrynKbreU
-N/x772Y1HQxDIGT1USjrkijo/JyA2371qLono+CODXWgK2NQ7r0tx0Cz22NCtcbe
-qf10yhVjl5S5OWRv77Y2l6z8bLsX4JfhPuUtpEgNNdl5WI2Wg3W2OnLU7I0nGFWa
-+8g+NgId2U1vOxZVrcUNEmfNPL3UZxiV4h48o+PsjShlpgUpFdRlp1/oqeB+vv7a
-huXHNv6FbqnlqloQRZgJ6b73uu8dOPm7aNwozIQCPmcvF7dZW9rTvwh5atieo47D
-V6jeIZw7ijwiqWlKCXytQZYHI6tM7op4KLHgXle7Fep2WTnUUwtN2H6hjWVO6Aiw
-16n/NXAfCgng7VCQfF0+wujKWlzHRsF6aTRWS+G7E5I2BrJeQMNqX4LGjac04NSs
-6uvW7GI4hQlFHYMqGGNvjIqqhRXUxrLbBN3h32doLHtIEbPzbmVVd5vFhfrZUSyz
-lJLkM98r6vkzBE6yhquDmUzq/7Tnaizbe5eN04fdKGtQThDXDHNKVGXoK5KGpPSJ
-yreTfYIoKllZ13x1QQUb+yw1d9meyXi2Bh9vXOePLMJZ8HvdldWwII+FiNsq5JrF
-BWvxqXV+0AOBpKpkM4Ht5CJIePTmqkgiSgaq1AtD5Fi3Ltd6IKFBXZfkpNa9i9ss
-HVnVx11ISin++a9ZmbePDXvrLH6XyFA0fwi3MRW/cURKQY/vrGGjyEZC4jf+Ep4X
-z0FWdGmE4Anv7UQplz3X9KLiDJ3b7BNSw9m0/+x0cpNwqNB5yr14SsGr74X/N8qw
-5zxn9ADr8Zt0VUomoRq2kdZfr4k6yE+eM3ftGi46bRaOpttxr1oHq/WLi3AKI2pf
-WpBG6B9ZDarU+lSBy13W80eN0ynw4V1BGvmoRyKj3rlJc4uV6tcjMqJM8nWDY87m
-LsUyl9ejlREm01DWdajyVmKv1uw5grHsnWL94qfrkdTYUDJ3TnvpoVU9uSYVRZSg
-Lkg8ncazt/XLx43H8UpX1GTfiCQn+9JQk+QRReuTZC2rCrIIxZQgpblsfLXT2jxv
-zT5iASiWqihSixJTSjbRJ2R1hdQASUWVvvUhpR62a1DW1cmwLXcJdP2zCqHuQZK+
-KSTf+iFVyQ6nIBiCf/M8Km7TAHQCfvXd7TtDX3x178Gv6PsC6zt4ul671t6ptZRn
-HaP62TwBUXR2mIQ4NgJz6Y4B7NNZinX6vxf0nz+x/mjzx0tsFNxX6eiWCJV5UErK
-gp71WMnaoTX9yreOQrkhKKQDwyk1hz1Bik7Hy7eXFTbc6+tgdvgbKOqBV7lqr4MJ
-4WS/kHVVueZjLLCuzNb0Q1oq8n1J1HmQNgwa85YxWrWLedrydprLN7pJxGA+kGRN
-V7Oi1z7dCQHHOmJmE6zqnDVdwqgSfEELXmiUDLrPKH+Oor/KehR987245/v62x06
-prXhnw5iQzRECY7Vsyk/TwGybL/ccKuEsjvu4rFnOosRw76FzuzC3111VjGqgE9+
-C+h3DXS+sT0AEhjYaM6Wrfm1xuMpjCrekjRc8//ughSnoxxp5dbi962tGXKfISEg
-UL2F0vaZ+s33bn73XV970T0hDR88AD5E7n650YFNriAbbh+75HZdS9TCKvU3axjN
-x4jpXkDzxUnj9CVGZfdrCzY32OmgB2SpMvDSHhkB/AEGhCQ9AKo0Di6s+TX+OccZ
-vtlx3Ngw2uI1D57ax+dtW+FjqQNZ/9iJ/aJIxwDQKsOuvFXxH/hQ7d9WxVFpPDZu
-8Vj0ifNuRkDpegQpf6ziRsWdspm/p6UKNnI+wtRnc65G29/70NjQeZnwdwWCZutK
-FBer3MerbnNUUfJEeIyPtT9EcToNEPan3k7XJOqSzjCq2t8/b/z0mISVZ9vN0mU0
-kYB/RS0MhMKohU4W5ToxAUHDXpwOeuidbF6Ha8DwVty57esyb9dY7Yve7CdePDSh
-MO6d/hXJHaKSgA8eXEdUn2651pIzhuvkQ2OZlOKd6RnO+a/p+T7p7sEJd7C85wvz
-m5k7vhAe130cgmH9HVh0YiS72oV2dnM2oaobrg+878thIg2kBH6AxNo7tedyXU4x
-0Fn/xQDg24jxGz9VlQnNW1J5wG387q8G+XK1TDPLIbVONl58QucUO420eGp3RgU5
-CXnUExoZvROrC9QQp/yDwpsYvaQja52J3RvAzj/CuWmMagTeXZnBp2CA0Wr97GH9
-7RV9zZ6ncJ4t2nTHmttj1mjHfYj2p74QRHZRYHNPLp4MeTltZ9kIqm5GiEKv7JOf
-a3Puv+6ldIO1LiPvRwKh5pMNBEYPHlygg7dTGO02lmYaqwTj0LfigHtWXbxe48cB
-7O2cNVW2pvP18/nWHh2bYe9ROcT3zxtrL62zMwKk2g7ODxl7Env07ED7fPfpa6p6
-jYRT4bA0/5HDgRs8YmOZh18g1RTosMwBhZczGK1itO75LCYq1oVLVHVfVmt2fskq
-RM+NhEv3Gf0uRIsqzoKiEPTc2Dq1v3/ukcNYZt95e+aQvHNy/b3KEoKAuOP6PicP
-J3UfjitjMK7kbF69sQp7cVmTeXio1knRsI6Ngv0T7bLGTwXGSug7a/C7Gi8rf9/C
-O4QbZtvBh6iKb9aY1rw1bJT87wihLHzm/N13ffTDdnUgO5ySRLfmcgaA+RHBEg1F
-R7RbWmwPLvQyA3yji0hxmN0dw3EeUprlQ/uH7zGqUYz2GdREVcqQHQ8e9PXGJezC
-2tO4/omz9jir++2qQi8hDCm7S/+UzuiTvs/To1YlOvLHLf4LTKUUoEJRytCZcOh9
-9wpu6HzT//X9LwPfbcav9n281m15hgCrUSWVCJ89cTfF/pcG4nj4RwSDa+91vxOX
-XPs/Y9Dz4riF7PsJHcrdKHoWdr+9zyFMkf9PKVrswb+SU5IM6fV2k4BbGrbsHv9s
-RBQwBv4jq+hCMB71sCey6IzcEQFJu+7zujI3fADVtAaUEaBBlWWkUWEcgmEIZZDN
-JATfsMP/BQAA///J9LxLHEYAAA==
+H4sIAAAAAAAC/7xbe28bR5L/P5+i7SDYBLjIm1ssFqe9vVvH2ezmEDs+S8H9c8Bi
+NGxSE5HTvJmhtEpggD2jB0XJkaxnZMkr0Q+JJiXSinSxLMnWd7nmDMlvcejuGXLe
+pJxggcCxpa5HV1dX/aq65n0wrAiymhY0pKiD770PPlVyMgK3JXEUpv8J/POvP/nd
+e++DOwJK5jIS+FeZ/eWPqYwgpQdElPk3e0lGTUkJcP06/YuqKfRv178UVO3jLvfB
+nlz+W2ZUcionpODHw1DIDIL/ELKCDFUIPhzVtKw6eOPGxMTEgEa5Skn4N0p9Q0Tf
+Tt7QoJBRb/zmX37329/c+Ea48ZGH2SD4RmA/uJvOKUL648+RklEHgZxl/1T/8Mnv
+Af/rH379e7rO2c+wAiG4mchIsqRqiqBJ47C7xWat1Fya8S2+O4o0pHYXmTObze0d
+36Kvs2kkJGACJBWUAbfQt5MBOvZDYqwR/QUxCgTPE32O6E+IYRBjgxiHxLggxhzB
+GwS/ZX/6ZXwqiGMwAXJZLiQzCTJoREq79G/NVszCDME1YjwhxhLRnxGjaksylqgk
+vd4VGS1paFRQYAJMSNooyEC3C3iW3UEgjeQUVIDKCMIWfolSkgxuKTABZU0S0iqA
+ioIUlzmnn5vFLa5G63jW2r2wjGlz94jghfb6ShuvEfyU4D2Cp5i2mySvE10neKZx
+mjfP9og+RfRic+uEcdgjeJHgXUKppkhe7+rx9b0vwWeSKqJxqEzG6cAPjy7/+Rr4
+zfBfMC0it0GJXiB4huAVgh9fi1gNZMFN8oEKKHN9heRxLPldQVUnkJIAozCd9bsh
+rlI/oN5wTvTXdFP6PP0hrhPjIf2JUbf9UV92WSd2dx2BSQmmXc7g4xhJpo6iiUgq
+oi+3SuXms7NI8pGcpiHZx6U/mlEp4bJw+/Hfw8m+RHIKDEFVlZAc7etDuZGMpLk3
+ckj0l+wuHgfuBZJlKGpASGpQAQpUoQYU+D85qGowATRJc99uYpSYLapEXyZ4tfnk
+rFV54D6Qa1dj7/WL6+9dJ1gnuELwDsHV5txrs/Cc/rMjlYaVCjGOmdsst6n7FTsR
+hOR1wBzRs4j+Sf/JAo/tZGXquL7DxQt0mX7OIlOB+fdC57KB1uGe+bA4CJiKXERH
+p7pL6Vrr8pVlPOz+1g62VWLkCa6aR0WCF83Fest4Y+X3qVCsO3vY5BvYJPg1c/Oa
+h1hfdqwdG2S41e9B0bZ74AD9Lh3FNZplyKGt0GBA726J4Po1ECtlh6aCPG6Vj8zF
+OjG2Hfv7wgHTx51DaNLYoGeET6lt3Iv1ZZubfb7zBL9gUWme6MvW0RnRcdBmgODH
+7Iy752cdlJoHBwTvE7wZ6cks8yEhp43+csYN4f0PtHLHsvoRXaa/IsY+vT/0Ssyy
+n1xGROsVepfezfpsR3EHAOJPgOZ7SU75z8CTm3wW64uf1+7vnoqGJxBICqKGlLhU
+b/PXjztR6JdEHAFNwtOiIz2G8IoJnNq+G8jbedy4LIVv+J0MmoDjkgiBpuRULbAn
+Hp6pgGNirBLjue3B9M/lxmWpvXvBde1XgM8jbP4Vemc6V4XmGZZz6P67SaZxXjTf
+LjgZY9YOZtRY9cbZQmsPN092W5UHrfIFwQvWkU6vCoXkPPNsEX2lq+RX8ggSlAT1
+0TtIA4KoSeMCTaLD3hvAD4cqxA7HmCH6U2JsMnsXuHLm5XRrD/uyTx+Sbo1CcQzQ
+Akv1haZi480l89YasJ2jzrjuhmjRjS88x3bcfItdWx14UIaBib7vpG8nXEVx7CPv
+M/WYzjUOiNj9LjjJvNrO/0jwZefa9WMVJGuCqIGc6vaSCvPlbn1D8Py/A4KL1suN
+1vkb5idFc22R4ClzqUD0Rbr9UO+nSDE7qggqtOHTX3pEKC+O4SbTKU7XeWqY4vGV
+KhQjJYgh4+SEMpJUm9fwu6PIMHafosRkJGoEH9JzZnv+CLggpMszutBt/x8HIVmn
+gJ8/jUPnPxD80Be4r4Ys87idf9Tcec6KsDfONXjqB53GRZ+4c4Vqq8/5cScLm31B
+z7Cj4pH1U1bjhNcjxHjEZJwSXLUK55647HFKGU74XN9af2k7dESWjuH0eZ8FYoCw
+972wtk6s9Zf+7PI5UlJIA1m77ou9WLhoXv7AnCd4UW/mtFGkSN9C/61iyKfm9hin
+qbPGIiV3qRDsbM1dtioPwiTczGYDdzcCLAImnmb+5sFB43SulZ+mfpefb5yd2d0U
+VrA5QKAb7sMED9lgLGyL80Sf65y8OX1kbc+FsbiNFLfa9DJS+Pt/+b2w1bfSEpQ1
+kKVeK2uC5imvo+GOVX7R3lwieMHJqPueRBrc0D1e+obhVVy3DkoOTmCIhXpC5zTL
+fKtOMpliUW7KhxMH42TfhUpGYp0DoGqC4vbhrph6nxwUKCSQnJ709zmYCR74EUVP
+VhOKpMEgr7L5bM6iMPfKTKGccCNuZrpuHOvE8FjvG5qURRcTWxWWAvASwdXGacla
+f+3CPPtm4UVztczjLEvxlU6QjT2aIZhOhh4HZz0IPlDjyLn3hjNo5582/7dkThd6
+MbuL0pI4Caj/Q1n0pOtOEVhrvLlsrpat9dfW8RoFS+tPbGMaj1lMeMXzRatySPS8
+XR/ihV7nZ4tOS/KYD2ivhC3/szQOQTbSm9v41Jw948kK9EM/Bie9ITk6IvpJPW7G
+MnF0Le2JzH3U1XnM3am1t9g8mSK4yHqtx4z/C5Y8l2yDu42Pq+bbFaclW7bDe/Wt
+E3Q3I3yebYzG+6jNUfQSvT8e/hfsNwS9ytEVqwNttYEDvM2ZaedXoQYJZKhfzCY0
+VJqL6+bbDV//4t1NlICq6EsUH36gfkQzceNtycw/o1hk6WHjtMgA0xaTusM6ItWe
+5gwkhDBnCa3lwoONH7n0CwM4oRNtXG9VLJqGplNBFmE6WtT8srnkysN/UhSk+JN9
+c/WY4I1W+di1MRsyEL1Mj5ue7EJz86y5uuOptNzHx1l/IWtQkYU0GILKOFRAqEDq
+TdRHyh6MEMfgNlRVIeVlESyErR8LLL/v05/r886Lyb6NvJv7mN0BftSY+e4uh1Lm
+tGGjYrxpFitmcYthgg1fayiorKrRAwAy0kAS5eREcKsrLg3ZdTPmiHHAWxPm4Q/m
+dtkN0/qQELCF3dcxdhjT/VblGbPujluY+eaJebHobQLtxJUpjTfbVmGpcXpI74K3
+juu2mPzpM7DFPgsavteb2WxaEhkkjDZof0QBG/VHdlPUIp57OFVYA8JcW2yXFkge
+t44r5toiaz0E2g11P6c7iCZTDYKsoAgZqEFX25L/glYr9OqVnJBUNy+n27sFP/Tt
+8BMZNvmrlAjj2f3llfkqMCEpUNT+mlOkMNae31+ZuyqibLgV2C/eQduUpGpQgQnb
+IO7YWLdzF3XRY2IUqH9unrcXfuyrW9fVmcfnCFMHr7CIFGogjyX7td+Co6CrhUdR
+oG9ZuXGab82exIeScSEtJd5NC+vwKeO96MsR0ULULJJVCLTJrAfhsrBAIQNrB9La
+6xmbT7iyBOYfriQ2VTKLr1kd0Gl6b/hpb+dUDYxAIOS0UShrNAC4JxmcBrHH1H05
+hWvbUAMaGoNy/41DDuudLhiuN3dPrKdTjho7tBDPY2t7p725ZBZmO90Kvw73mGwh
+Tau8ye7Tb7QevPfW1aNubTwhuNraw9aRHugZb3obxrhmLm7QTGAU2KE+I7gc9yQb
+nQmuRRkzI0jpoC27HU1Pjfnz7ddxLD/68i90ikHH1IIowmzI+0C/dO8gyd/ncw3r
+TCDwOX9buckb556MFvIYsj3HLo67hvaOCd1CclJSMjxZfq1Cngcj62DXEbnBzoJz
+XJ1mrdMHduGyeiik8CutL7uUjoCj3Q6FCu5BIQG8PRSaryuHBF+ai+tEL5ov9eZq
+OZw6IaljIOeFE7w6p/WC/pQFnLpZe92eXQznMIGUMaiAMf4KihQ1rOTXl5027WP3
+CxKLZQ8Yprdf1szaTqu00Dg9jBWWRil35nvFbv4MBby8JWyjOoPdf9YV1pet3Yvm
+yYNenFUoJ+jVDLuUuMbxYSQPCQ2I6NvJAUEUUU7WVF/lUiX6Hk/NPcizWQ9p8HnJ
+ufyRbQIe/F73FDUiyGMh6raL+VZpwVx8ap7t98EgpaBcNkBOD4KGR2+uimSCslBh
+tzBEj3XzYq0PFirUNElOqb37zK3yoVl71IOllHY/ULaq89aRbm2dxlOJHEW7N+G0
+zuIJk1Iaeu7OGtFLfGglnvCXuHnxEmSkSUm7oOjDuPxBqR8TZ9lk6YCQHsll/Htn
+s6VUQpVNfO7GcwoefT/yv0Ejnv2csg2sxxNpipRKQSWMkFWIr6k56E+e8+vaM1x0
+G0Euns6bQM3cX22cn4dzSCoDGUFKsj9yKlSY9ymCK3eZzx82T6bAh7cFKflRn0xG
+vZOdxhZvJlyNSRJNuusG252NHYZlLq7GKytMZqCsaVBxe4m1WrfmKMayHpca5z9d
+jaXKx6Zd+7SWHpi14ytyQaIENUFy82k+e9u4eNR8FG90pKQGkpKcGshAVZKTSB2Q
+ZDWnCLIIxbQgZVzZ+PJxe/OsPfuQB6BYrqLIPEpMo1xiQMhpiNYAKaRI3wpRtX8k
+uQplTZkMI7lNoeufFQg1D5L0zUn51g8rKDeShmAY/s3z7LnNAtAx+NV3N28Nf/HV
+nfu/Yi8gvO/g6cvtmLsn5lKB97Qap/MURLHpZhri+JDOhTOosMemPdbZfy/YP3/i
+HdzWjxdELzrv5tFNG6bzkJSSBS3n8ZK1A3P6lW8dg3LDUMgExmfqtniKFO2enI+W
+Fzau9+Gh3Mg3UNQC74a1fkcnwtl+IWsKuuJzMTAvjfb0A1YqujunuPtkruss5i0T
+vGqVCqwpb7e/r/XSiMN8IMmqpuR8vSlnhsH2jpjpCbM2Z06XCa4G3/iCBxqlg+Zz
+yp9j6K9yHkNffy9uwKDx9jEbJNvwzy/xMR9qBNvr+RyipwBZtl5uOFVCxRnI8fgz
+mxaJEd/Gp1bx7445awRXwSe/BezLCzaB2RlRCYyUtGYr5vxa89EUwVVvSRpu+ZuK
+OCqNx3q3G7E8sd9/KHRZj2Dl92jXyLNdXLlYmktVoud9jNnJ5h1U3vluhXlQt8Pu
+rx2jNxfn0c4jTK95oCh9etg1wpFdNg0w9gfobm0ddUinBNes7583f3pEne/Zdqt8
+Ec3EdzzRCwMXJmqhHWtd9XpA0bCXk/0+KuzNq0gNON6KM398VeEdJN456M1B8N13
+A8MTiEvvdjlohBFRAt6/fxVVfbZ1NSDscVI7aurLtGDrToHQcNIJPHZJ88cuNhBF
+NsiCV3ltEz5xyLS5AyecAem+D8zvZs4zfKB3EyYh4HbvIqI7aMePdqETA20iXGu9
+OG6evLTPLF6lu2nBPQhh7p5Yc/keu7jbXf/FXeBuNsUTfqqgCdULvD0QKJ76qyF3
+UVNhQ3UHzDv5mOwxm7frtlviud0aFeQUdOfG0MjonbxcYI445R943ST4JRu96k6e
+XgNW4SHJTxNcpyDg0gg+aQKCVxunDxpvL9mr7DwDfXzRpjOe2xkXxo+dB1WX9/Mp
+9GDePi/y+R0HdYS8ANoeFMnVyQhRGId/unJlyYNXPZRe4McR5B12D3WfXCAwelDD
+AhsgnSJ4p7k001w9IrjOXhQD17PmoLq6+1nb2s6bUxVzutA4m2/vsvEP/mqRx+4u
+a3PtpXl6SnCle8Hdw7KexB79Bt7Z3z325qZcIeFUXYjLPay/7wSP2FjmkRdINUU2
+9LHPBqJmCF4leN3zeUdUrAvXqOa8v9WtwpJZjJ5/CNfuM/Z9gxoF4YOqzBN9rrl1
+Yn3/3KOHvsy/V/bM03jnvQb71SUEAbm26/ssOpzVPTiOxmBcYdK6fGMWd+OyJr/h
+oVbXl3lb3vqJ9eLip9tiNfTtNfh9iFeUv7r1DpOG+XbwuaLqm5lllVGd6GV/tzlU
+hM+dv/tugH2grdzNjaQl8Y6QgffvdwZZ3aNuZRaKDllPrdR53u5nlvVaD5XiMLsz
+TmK321uVA+uH7wmuM4z2GVRFRcpSivv3B/qTEnZgnalS/+RUZyzT+QYTsUMIQ8rO
+0j9lstqk7zPrqFWJrv5xi/8C02kEFChKWTbbDL2vI0GC7rfpX9/7MvD9Yfxq30dY
+vZZnKbAaRelE+ISCQxT7xXycDP+oW3Dtnd5n4rDrfI7f9+K4hfw7AA3KvTh6FvY+
+vc8hTNP/p5Eau/Gv5LQkQ3a8vTRwLQ1bdsf9uEANMAb+M4c0IRiP+qCJLDojKVAy
+CRU1Cpn2S+692H3QJRXoyTDq1amjZA5DJaMClAQqVHhOHBXGIRiBUAa5bELwPcr/
+fwAAAP//H8/tvWZFAAA=
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /locales/nl_NL.po
-Size: 17520
+Size: 17454
-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
+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
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /locales/pl.po
-Size: 8921
+Size: 9119
-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
-AA==
+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
+hAWigqbOjq/R/h8AAP//xZUEwp8jAAA=
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /placeholders/thumbnail-large.png
@@ -37022,47 +36873,46 @@ HUKJeoKBJ8xtwSdHdN72SUwE+97TziN4tsuT+L5PW5c+6V37YeDKZDU0XfAh7z5J
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /styles/stack.css
-Size: 7721
+Size: 7604
-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
-KR4AAA==
+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
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /templates/authorize.html
@@ -37146,21 +36996,22 @@ u5u8u8Az3v2C+zcAAP//UWoXN9IJAAA=
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /templates/error.html
-Size: 1531
+Size: 1661
-H4sIAAAAAAAC/5xUTWsbMRC951dMBx9ji9xK0C6lSW6F9hAohUKRtWOvsCwJaezU
-Wfa/F+1H47U3UHpJdmee3rwdvWf54fHrw/OPb09Q896WNzL/A6vctkByWN4AyJpU
-lR8A5J5Yga5VTMQFHniz/IhDiw1bKh/860mK/vnsiFN7KvBo6CX4yAjaOybHBb6Y
-iuuioqPRtOxebsE4w0bZZdLKUnE3DrDG7SCSLTDxyVKqiRihjrQpsGlUSsSwevR7
-ZRyg2HjHqf+70ilh2/4fT48RiZXevUtktHcIfApUoNmrLYngtu9zdpAkahXCSVt/
-qFYZ3rYI4lpj7SPrA8P1jN/LvvbuCtQxA1ZG+1G1FONlyrWvTuMVZXz0lgpUIVij
-FRvvhs8EkIl0LoC2KqUCgw+H8Lc7GITiWwFAqkFVzRzSvRDav55WxiOwitvsnV9r
-q9wOobNKgdk38J3WyTBhKYU6oxeX/LIyx1FMdpIyjiJO5td3ZdOYDayeYvTxOQ9p
-26bhywLZNDSwa0DXwa7lqraVor6bEFfmeP4+FUOZAqf9KUJZinyFAGiaBcUI9wWM
-Ett2DqR6UArWMHRH8KfDWWxUbkuwMLewCPlMPjsDzFCzAUcZhjiLkKFsmkXI6wjl
-LEO3rJt/rctQysTRu215tvqHfJWa4ZAQ2vbNQ3tlLPt73bc/ZSv1qdEay7lqts9K
-imHCjGYprq/xsnRV6P30+cDs3eSb5MZ7nvq/S8B5XJZrPkvqwPLFuF0OZufLkXji
-/Szjmv1yrROpUgxxHcItcrr77PeRl6L/qf8TAAD//xp77oD7BQAA
+H4sIAAAAAAAC/5xVUWvjOBB+76+YG/LYRPTtKLK5u7ZvhVuWLsvCwqLIk1hEkYQ0
+STc1/u+LbKeNEweWfWntmU+fPs98M5F/Pf7/8PLt0xPUvLXljcz/wCq3LpAcljcA
+siZV5QcAuSVWoGsVE3GBO17N/8YhxYYtlQ/+7SBF/3xyxKktFbg39Bp8ZATtHZPj
+Al9NxXVR0d5omncvt2CcYaPsPGllqbg7XmCN20AkW2Dig6VUEzFCHWlVYNOolIhh
+8ei3yjhAsfKOU/93oVPCtv0znh4jEiu9uUpktHcIfAhUoNmqNYng1tc5O0gStQrh
+oK3fVYsMb1sEcamx9pH1juHyjp/zPna1BGqfAQuj/VG1FMdmyqWvDscWZXz0lgpU
+IVijFRvvhs8EkIl0DoC2KqUCgw+78J4dDELxIwAg1aCqZg7pXgjt3w4L4xFYxXX2
+zo+lVW6D0FmlwOwb+ErLZJiwlEKd0ItzflmZ/VFMdpIyjiKO7q/vyqYxK1g8xejj
+S76kbZuGzwNk05DALgFdBruUq9pWivpuRFyZ/en7WAxlChznxwhlKfIFAqBpZhQj
+3BdwlNi2UyDVg1KwhqE7gt8dTmKjcmuCmbmFWchn8tkJYIaaFTjKMMRJhAxl08xC
+LkcoJxm6Yt38fjy35t/OVV8+P8MERIby3URN84HNRu762EeGRmbDTGq7piDTJ47e
+rcuT5j9kM2mGXUJo2w8Xb5Wx7O91n/4nm7mfW62xnIpmPQsphhsmlElxaaTz0EWg
+L9t/O2bvRt8kV97zeAK7GTwd2PmST3bFwPJs3Oa9okfi0fRlGZfs52UdSZViWBjD
+ehF5v/Tbp186UvQ/Nr8CAAD//9Kzyvl9BgAA
-----END COZY ASSET-----
-----BEGIN COZY ASSET-----
Name: /templates/login.html
diff --git a/web/status/status.go b/web/status/status.go
index d0b6130acf8..cd9d6dc2bf4 100644
--- a/web/status/status.go
+++ b/web/status/status.go
@@ -14,6 +14,7 @@ import (
func Status(c echo.Context) error {
checker := checkup.HTTPChecker{
Name: "CouchDB",
+ Client: config.GetConfig().CouchDB.Client,
URL: config.CouchURL().String(),
Attempts: 3,
}