Cloud
Global

Cloud

Cloud is a service that allows you to upload your files to the cloud and share them with others. All of data is encrypted in the browser before being uploaded to the cloud. The encryption key is never sent to the cloud and is only stored in your browser. This means that even if the cloud is compromised, your data is still safe.

How files is managed?

A file node is composed of some file stored in the history. It has a current version based on the last verion of the file in the history. You can add a new version of the file to the history. You can also delete a version of the file from the history. You can also delete the file node.

What is a node?

A node is a element of Secrecy Cloud. It can be of file or folder type.

The two types follow the same structure. But a folder can have children and a file can have a history.

Folder

const folderNode: NodeFull = {
  type: NodeType.FOLDER,
  id: 'ckudra3tf096901az84r3hfeg',
  name: 'My folder',
  isFavorite: false,
  parent: { ...parentFolderNode },
  parentId: 'ckumnslj1692401b1p79ubsq1',
  breadcrumb: [
    {
      id: 'ckumnslj1692401b1p79ubsq1',
      name: 'root',
      pubKey:
        'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
    },
  ],
  children: [...nodeChildren],
  current: undefined, // If type is NodeType.FOLDER, current is undefined
  currentFileId: null, // If type is NodeType.FOLDER, currentFileId is undefined
  createdAt: new Date(),
  createdBy: {
    firstname: 'John',
    lastname: 'Doe',
    email: 'john.doe@secrecy.me',
    id: 'ckudqxwhb001701831v1liryi',
    publicKey:
      'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
  },
  updatedAt: new Date(),
  deletedAt: new Date(),
  history: [], // If type is NodeType.FOLDER then history is undefined
  sizes: {
    size: 0n,
    sizeBefore: 0n,
  },
  users: [...users],
  access: {
    isRoot: false,
    rights: Rights.read, // It can be read, write or admin
    sharedBy: {
      keyPair: {
        pub: 'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
      },
    },
    userApp: {
      user: {
        firstname: 'John',
        lastname: 'Doe',
        email: 'john.doe@secrecy.me',
        id: 'ckudqxwhb001701831v1liryi',
        publicKey:
          'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
      },
    },
  },
};

File

const fileNode: NodeFull = {
  type: NodeType.FILE,
  id: 'ckudra3tf096901az84r3hfeg',
  name: 'MyFile.txt',
  isFavorite: false,
  parent: { ...parentFolderNode },
  parentId: 'ckumnslj1692401b1p79ubsq1',
  breadcrumb: [
    {
      id: 'ckumnslj1692401b1p79ubsq1',
      name: 'root',
      pubKey:
        'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
    },
  ],
  children: [], // If type is NodeType.FILE then children is undefined
  current: {
    createdAt: new Date(),
    id: 'ckudra3tf096901az84r3hfeg',
    md5: '66552322bf3c331a53742ee471a90f02',
    md5Encrypted: 'c6884509924c4f4e3301685fe049849b',
    size: 0n,
    sizeBefore: 0n,
  },
  currentFileId: 'ckudrwube272001azozlz6tjx',
  createdAt: new Date(),
  createdBy: {
    firstname: 'John',
    lastname: 'Doe',
    email: 'john.doe@secrecy.me',
    id: 'ckudqxwhb001701831v1liryi',
    publicKey:
      'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
  },
  updatedAt: new Date(),
  deletedAt: new Date(),
  history: [
    {
      createdAt: new Date(),
      id: 'ckudra3tf096901az84r3hfeg',
      md5: '66552322bf3c331a53742ee471a90f02',
      md5Encrypted: 'c6884509924c4f4e3301685fe049849b',
      size: 0n,
      sizeBefore: 0n,
    },
  ],
  sizes: {
    size: 0n,
    sizeBefore: 0n,
  },
  users: [...users],
  access: {
    isRoot: false,
    rights: Rights.read, // It can be read, write or admin
    sharedBy: {
      keyPair: {
        pub: 'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
      },
    },
    userApp: {
      user: {
        firstname: 'John',
        lastname: 'Doe',
        email: 'john.doe@secrecy.me',
        id: 'ckudqxwhb001701831v1liryi',
        publicKey:
          'p48zca45s4cm9b3p7p6x2d1z5nqnj3458rvwhp6x8y5gnam556985g15789187s6',
      },
    },
  },
};

How the file is stored?

All of file upload in our cloud are encrypted on the client side with the private key of the user. The private key is never sent to the server. So only the user can decrypt the file. When the user get the file, the file is decrypted with the private key of the user after the download on the client side.

You can find the encrypted protocol here.


Get the client

import { getSecrecyClient } from '@secrecy/lib';
 
// Get the client
const client = getSecrecyClient('prod');

addFileToHistory()

Add a file to the history of a node.

const res = await client.cloud.addFileToHistory(
  fileId: 'FILE_ID',
  nodeId: 'NODE_ID',
);
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorNotExist':
    throw new Error(`Not exists`);
  case 'SuccessResponse': {
    const node = response.data;
    // Do something with the node
  }
}
 
💡

By default the max of history file is 10. And you can change this value with the function app.updateSettings().


uploadFile()

Upload a file in the cloud.

const response = await client.cloud.uploadFile({
  file: new File([''], 'test.txt'),
  signal: new AbortController().signal,
  encryptProgress: async ({ current, percent, total }) => {
    console.log({ current, percent, total });
  },
  uploadProgress: async ({ current, percent, total }) => {
    console.log({ current, percent, total });
  },
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorLimit':
    throw new Error(`Limit Reached`);
  case 'ErrorNotFound':
    throw new Error(`Not Found`);
  case 'SuccessResponse': {
    const fileId = response.data;
    // Do something with the file id
  }
}

uploadFileInCloud()

Upload a file in the cloud of the user.
If you don't put a nodeId the file will be uploaded in the root of the cloud.

const response = await client.cloud.uploadFileInCloud({
  file: new File([''], 'test.txt'),
  name: 'test.txt',
  nodeId: 'NODE_ID_OPTIONAL',
  signal: new AbortController().signal,
  encryptProgress: async ({ current, percent, total }) => {
    console.log({ current, percent, total });
  },
  uploadProgress: async ({ current, percent, total }) => {
    console.log({ current, percent, total });
  },
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorLimit':
    throw new Error(`Limit Reached`);
  case 'ErrorNotFound':
    throw new Error(`Not Found`);
  case 'ErrorBasic':
    throw new Error(`Error`);
  case 'ErrorNotExist':
    throw new Error(`Not Exist`);
  case 'SuccessResponse': {
    const node = response.data;
    // Do something with the node
  }
}

duplicateNode()

Duplicate a node in the cloud.
If you don't put a folderId the node will be duplicated in the same folder.

const response = await client.cloud.duplicateNode({
  nodeId: 'NODE_ID',
  customName: 'Custom Name',
  folderId: 'FOLDER_ID',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorNotFound':
    throw new Error(`Not Found`);
  case 'SuccessResponse': {
    const boolean = response.data;
    // Do something with the boolean
  }
}

createFolder()

Create a folder in the application's cloud.

const response = await client.cloud.createFolder({
  name: 'My New Folder',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorNotExist':
    throw new Error(`Not exists`);
  case 'SuccessResponse': {
    const folder = response.data;
    // Do something with the folder
  }
}
💡

By default, the folder is created at the root. You can create the folder inside another this way:

const response = await client.cloud.createFolder({
  name: 'My New Folder',
  parentFolderId: 'folderId',
});

node()

Get a node in the cloud. It can be a file or a folder.

const response = await client.cloud.node({
  id: 'NODE_ID',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'SuccessResponse': {
    const nodeFull = response.data;
    // Do something with the node full
  }
}

If you need to search with more precision, you can use the deleted parameter.

const response = await client.cloud.node({
  id: 'NODE_ID',
  deleted: true,
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'SuccessResponse': {
    const nodeFull = response.data;
    // Do something with the node full
  }
}

fileMetadata()

Get a file metadata of a node in the cloud.

const response = await client.cloud.fileMetadata({
  id: 'FILE_ID',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'SuccessResponse': {
    const fileMetadata = response.data;
    // Do something with the file metadata
  }
}

updateNode()

Update a node in the cloud.

const response = await client.cloud.updateNode({
  nodeId: 'NODE_ID',
  isFavorite: true,
  deletedAt: new Date(),
  name: 'New name',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorNotExist':
    throw new Error(`Not Exist`);
  case 'SuccessResponse': {
    const nodeFull = response.data;
    // Do something with the node full
  }
}

Parameters

ParameterDescriptionTypeDefault
nodeIdThe id of node.stringrequired
isFavoriteIf the node is favorite.boolean-
deletedAtThe date when the node was deleted.Date-
nameThe name of the node.string-

fileContent()

Get the content of a file. You can use this method to download a file from a mail or your cloud.

const response = await client.cloud.fileContent({
  fileId: 'FILE_ID',
  signal: new AbortController().signal,
  progressDecrypt: async ({ current, percent, total }) => {
    console.log({ current, percent, total });
  },
  onDownloadProgress: async ({ percent, totalBytes, transferredBytes }) => {
    console.log({ percent, totalBytes, transferredBytes });
  },
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorBasic':
    throw new Error(`Error Basic`);
  case 'SuccessResponse': {
    const fileContent = response.data;
    // Do something with the file content
  }
}

deleteFile()

Remove a file in a node history. You can't remove a file if the node does not have at least two files.

const res = await client.cloud.deleteFile(
  fileId: 'FILE_ID',
  nodeId: 'NODE_ID',
);
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorNotExist':
    throw new Error(`Not exists`);
  case 'SuccessResponse': {
    const node = response.data;
    // Do something with the node
  }
}

deleteNode()

Remove a node in a cloud and put it in the trash.

const res = await client.cloud.deleteNode({
  nodeId: 'NODE_ID',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'SuccessResponse': {
    const success = response.data;
    // Do something with the success at true
  }
}
💡

By default the node is removed from the trash after 30 days. You can change this time with this function app.updateSettings().


moveNodes()

Move nodes in your cloud.

const response = await client.cloud.moveNodes({
  nodeIds: ['NODE_ID_1', 'NODE_ID_2'],
  parentNodeId: 'NEW_NODE_PARENT_ID',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'SuccessResponse': {
    const boolean = response.data;
    // Do something with the boolean
  }
}

saveInCloud()

Allows you to save a file that you had upload or sent/received in your mails, in your cloud.

const response = await client.cloud.saveInCloud({
  fileId: 'FILE_ID',
  name: 'FILE_NAME',
  nodeId: 'NODE_ID',
});
 
if (!response) {
  throw new Error(`Error`);
}
 
switch (response.__typename) {
  case 'ErrorAccessDenied':
    throw new Error(`Access Denied`);
  case 'ErrorBasic':
    throw new Error(`Error Basic`);
  case 'ErrorLimit':
    throw new Error(`Error Limit`);
  case 'ErrorNotExist':
    throw new Error(`Error Not Exist`);
  case 'ErrorNotFound':
    throw new Error(`Error Not Found`);
  case 'SuccessResponse': {
    const nodeFull = response.data;
    // Do something with the node full
  }
}

Parameters

ParameterDescriptionTypeDefault
fileIdThe id of the file.stringrequired
nameThe name of the file.stringrequired
nodeIdThe id of the node to save itstringrequired