diff --git a/docs/backend_api/BAttachment.html b/docs/backend_api/BAttachment.html new file mode 100644 index 000000000..985ee21e9 --- /dev/null +++ b/docs/backend_api/BAttachment.html @@ -0,0 +1,2876 @@ + + + + + JSDoc: Class: BAttachment + + + + + + + + + + +
+ +

Class: BAttachment

+ + + + + + +
+ +
+ +

BAttachment()

+ +
Attachment represent data related/attached to the note. Conceptually similar to attributes, but intended for +larger amounts of data and generally not accessible to the user.
+ + +
+ +
+
+ + + + +

Constructor

+ + + +

new BAttachment()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Members

+ + + +

attachmentId :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

(protected) becca

+ + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

blobId :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

contentLength :int

+ + + + +
+ optionally added to the entity +
+ + + +
Type:
+
    +
  • + +int + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

dateModified :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

isProtected :boolean

+ + + + + + +
Type:
+
    +
  • + +boolean + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

mime :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

ownerId :string

+ + + + +
+ either noteId or revisionId to which this attachment belongs +
+ + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

position :int

+ + + + + + +
Type:
+
    +
  • + +int + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

role :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

title :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

utcDateModified :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

utcDateScheduledForErasureSince :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +

Methods

+ + + + + + + +

(protected) _getContent() → {string|Buffer}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string +| + +Buffer + + +
+
+ + + + + + + + + + + + + +

(protected) _setContent()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) beforeSaving()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

convertToNote() → {Object}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Object + + +
+
+ + + + + + + + + + + + + +

copy() → {BAttachment}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +BAttachment + + +
+
+ + + + + + + + + + + + + +

(protected) generateHash()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) generateIdIfNecessary()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

getContent() → {string|Buffer}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string +| + +Buffer + + +
+
+ + + + + + + + + + + + + +

getNote() → {BNote}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +BNote + + +
+
+ + + + + + + + + + + + + +

(protected) getPojoToSave()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) getUtcDateChanged()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

hasStringContent() → {boolean}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ true if the note has string content (not binary) +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

markAsDeleted(deleteIdopt)

+ + + + + + +
+ Mark the entity as (soft) deleted. It will be completely erased later. + +This is a low-level method, for notes and branches use `note.deleteNote()` and 'branch.deleteBranch()` instead. +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
deleteId + + + + <optional>
+ + + + + +
+ + null + +
+ + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) putEntityChange()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

save() → {this}

+ + + + + + +
+ Saves entity - executes SQL, but doesn't commit the transaction on its own +
+ + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +this + + +
+
+ + + + + + + + + + + + + +

setContent(content, optsopt)

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
content + + + + + + + +
opts + + +object + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
forceSave + + +object + + + + + + <optional>
+ + + + + +
+ + false + + will also save this BAttachment entity
forceFrontendReload + + +object + + + + + + <optional>
+ + + + + +
+ + false + + override frontend heuristics on when to reload, instruct to reload
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/backend_api/BRevision.html b/docs/backend_api/BRevision.html new file mode 100644 index 000000000..e97dc907c --- /dev/null +++ b/docs/backend_api/BRevision.html @@ -0,0 +1,2693 @@ + + + + + JSDoc: Class: BRevision + + + + + + + + + + +
+ +

Class: BRevision

+ + + + + + +
+ +
+ +

BRevision()

+ +
Revision represents a snapshot of note's title and content at some point in the past. +It's used for seamless note versioning.
+ + +
+ +
+
+ + + + +

Constructor

+ + + +

new BRevision()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Members

+ + + +

(protected) becca

+ + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

blobId :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

contentLength :int

+ + + + + + +
Type:
+
    +
  • + +int + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

dateCreated :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

dateLastEdited :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

isProtected :boolean

+ + + + + + +
Type:
+
    +
  • + +boolean + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

mime :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

noteId :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

revisionId :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

title :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

type :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

utcDateCreated :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

utcDateLastEdited :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

utcDateModified :string

+ + + + + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +

Methods

+ + + + + + + +

(protected) _getContent() → {string|Buffer}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string +| + +Buffer + + +
+
+ + + + + + + + + + + + + +

(protected) _setContent()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) beforeSaving()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) generateHash()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) generateIdIfNecessary()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

getAttachments() → {Array.<BAttachment>}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Array.<BAttachment> + + +
+
+ + + + + + + + + + + + + +

getContent() → {string|Buffer}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string +| + +Buffer + + +
+
+ + + + + + + + + + + + + +

(protected) getPojoToSave()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) getUtcDateChanged()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

hasStringContent() → {boolean}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+ true if the note has string content (not binary) +
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

markAsDeleted(deleteIdopt)

+ + + + + + +
+ Mark the entity as (soft) deleted. It will be completely erased later. + +This is a low-level method, for notes and branches use `note.deleteNote()` and 'branch.deleteBranch()` instead. +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
deleteId + + + + <optional>
+ + + + + +
+ + null + +
+ + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

(protected) putEntityChange()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

save() → {this}

+ + + + + + +
+ Saves entity - executes SQL, but doesn't commit the transaction on its own +
+ + + + + + + + + + + + + +
+ + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +this + + +
+
+ + + + + + + + + + + + + +

setContent(content, optsopt)

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
content + + + + + + + +
opts + + +object + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
forceSave + + +object + + + + + + <optional>
+ + + + + +
+ + false + + will also save this BRevision entity
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ + + + + + + \ No newline at end of file diff --git a/docs/backend_api/becca_entities_battachment.js.html b/docs/backend_api/becca_entities_battachment.js.html new file mode 100644 index 000000000..6b55ef905 --- /dev/null +++ b/docs/backend_api/becca_entities_battachment.js.html @@ -0,0 +1,284 @@ + + + + + JSDoc: Source: becca/entities/battachment.js + + + + + + + + + + +
+ +

Source: becca/entities/battachment.js

+ + + + + + +
+
+
"use strict";
+
+const utils = require('../../services/utils');
+const dateUtils = require('../../services/date_utils');
+const AbstractBeccaEntity = require("./abstract_becca_entity");
+const sql = require("../../services/sql");
+const protectedSessionService = require("../../services/protected_session");
+const log = require("../../services/log");
+
+const attachmentRoleToNoteTypeMapping = {
+    'image': 'image'
+};
+
+/**
+ * Attachment represent data related/attached to the note. Conceptually similar to attributes, but intended for
+ * larger amounts of data and generally not accessible to the user.
+ *
+ * @extends AbstractBeccaEntity
+ */
+class BAttachment extends AbstractBeccaEntity {
+    static get entityName() { return "attachments"; }
+    static get primaryKeyName() { return "attachmentId"; }
+    static get hashedProperties() { return ["attachmentId", "ownerId", "role", "mime", "title", "blobId",
+                                            "utcDateScheduledForErasureSince", "utcDateModified"]; }
+
+    constructor(row) {
+        super();
+
+        if (!row.ownerId?.trim()) {
+            throw new Error("'ownerId' must be given to initialize a Attachment entity");
+        } else if (!row.role?.trim()) {
+            throw new Error("'role' must be given to initialize a Attachment entity");
+        } else if (!row.mime?.trim()) {
+            throw new Error("'mime' must be given to initialize a Attachment entity");
+        } else if (!row.title?.trim()) {
+            throw new Error("'title' must be given to initialize a Attachment entity");
+        }
+
+        /** @type {string} */
+        this.attachmentId = row.attachmentId;
+        /** @type {string} either noteId or revisionId to which this attachment belongs */
+        this.ownerId = row.ownerId;
+        /** @type {string} */
+        this.role = row.role;
+        /** @type {string} */
+        this.mime = row.mime;
+        /** @type {string} */
+        this.title = row.title;
+        /** @type {int} */
+        this.position = row.position;
+        /** @type {string} */
+        this.blobId = row.blobId;
+        /** @type {boolean} */
+        this.isProtected = !!row.isProtected;
+        /** @type {string} */
+        this.dateModified = row.dateModified;
+        /** @type {string} */
+        this.utcDateModified = row.utcDateModified;
+        /** @type {string} */
+        this.utcDateScheduledForErasureSince = row.utcDateScheduledForErasureSince;
+
+        /** @type {int} optionally added to the entity */
+        this.contentLength = row.contentLength;
+
+        this.decrypt();
+    }
+
+    /** @returns {BAttachment} */
+    copy() {
+        return new BAttachment({
+            ownerId: this.ownerId,
+            role: this.role,
+            mime: this.mime,
+            title: this.title,
+            blobId: this.blobId,
+            isProtected: this.isProtected
+        });
+    }
+
+    /** @returns {BNote} */
+    getNote() {
+        return this.becca.notes[this.ownerId];
+    }
+
+    /** @returns {boolean} true if the note has string content (not binary) */
+    hasStringContent() {
+        return utils.isStringNote(this.type, this.mime);
+    }
+
+    isContentAvailable() {
+        return !this.attachmentId // new attachment which was not encrypted yet
+            || !this.isProtected
+            || protectedSessionService.isProtectedSessionAvailable()
+    }
+
+    getTitleOrProtected() {
+        return this.isContentAvailable() ? this.title : '[protected]';
+    }
+
+    decrypt() {
+        if (this.isProtected && !this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) {
+            try {
+                this.title = protectedSessionService.decryptString(this.title);
+                this.isDecrypted = true;
+            }
+            catch (e) {
+                log.error(`Could not decrypt attachment ${this.attachmentId}: ${e.message} ${e.stack}`);
+            }
+        }
+    }
+
+    /** @returns {string|Buffer}  */
+    getContent() {
+        return this._getContent();
+    }
+
+    /**
+     * @param content
+     * @param {object} [opts]
+     * @param {object} [opts.forceSave=false] - will also save this BAttachment entity
+     * @param {object} [opts.forceFrontendReload=false] - override frontend heuristics on when to reload, instruct to reload
+     */
+    setContent(content, opts) {
+        this._setContent(content, opts);
+    }
+
+    /** @returns {{note: BNote, branch: BBranch}} */
+    convertToNote() {
+        if (this.type === 'search') {
+            throw new Error(`Note of type search cannot have child notes`);
+        }
+
+        if (!this.getNote()) {
+            throw new Error("Cannot find note of this attachment. It is possible that this is note revision's attachment. " +
+                "Converting note revision's attachments to note is not (yet) supported.");
+        }
+
+        if (!(this.role in attachmentRoleToNoteTypeMapping)) {
+            throw new Error(`Mapping from attachment role '${this.role}' to note's type is not defined`);
+        }
+
+        if (!this.isContentAvailable()) { // isProtected is the same for attachment
+            throw new Error(`Cannot convert protected attachment outside of protected session`);
+        }
+
+        const noteService = require('../../services/notes');
+
+        const { note, branch } = noteService.createNewNote({
+            parentNoteId: this.ownerId,
+            title: this.title,
+            type: attachmentRoleToNoteTypeMapping[this.role],
+            mime: this.mime,
+            content: this.getContent(),
+            isProtected: this.isProtected
+        });
+
+        this.markAsDeleted();
+
+        const parentNote = this.getNote();
+
+        if (this.role === 'image' && parentNote.type === 'text') {
+            const origContent = parentNote.getContent();
+            const oldAttachmentUrl = `api/attachments/${this.attachmentId}/image/`;
+            const newNoteUrl = `api/images/${note.noteId}/`;
+
+            const fixedContent = utils.replaceAll(origContent, oldAttachmentUrl, newNoteUrl);
+
+            if (fixedContent !== origContent) {
+                parentNote.setContent(fixedContent);
+            }
+
+            noteService.asyncPostProcessContent(note, fixedContent);
+        }
+
+        return { note, branch };
+    }
+
+    getFileName() {
+        const type = this.role === 'image' ? 'image' : 'file';
+
+        return utils.formatDownloadTitle(this.title, type, this.mime);
+    }
+
+    beforeSaving() {
+        super.beforeSaving();
+
+        if (this.position === undefined || this.position === null) {
+            this.position = 10 + sql.getValue(`SELECT COALESCE(MAX(position), 0)
+                                              FROM attachments
+                                              WHERE ownerId = ?`, [this.noteId]);
+        }
+
+        this.dateModified = dateUtils.localNowDateTime();
+        this.utcDateModified = dateUtils.utcNowDateTime();
+    }
+
+    getPojo() {
+        return {
+            attachmentId: this.attachmentId,
+            ownerId: this.ownerId,
+            role: this.role,
+            mime: this.mime,
+            title: this.title,
+            position: this.position,
+            blobId: this.blobId,
+            isProtected: !!this.isProtected,
+            isDeleted: false,
+            dateModified: this.dateModified,
+            utcDateModified: this.utcDateModified,
+            utcDateScheduledForErasureSince: this.utcDateScheduledForErasureSince,
+            contentLength: this.contentLength
+        };
+    }
+
+    getPojoToSave() {
+        const pojo = this.getPojo();
+        delete pojo.contentLength;
+
+        if (pojo.isProtected) {
+            if (this.isDecrypted) {
+                pojo.title = protectedSessionService.encrypt(pojo.title);
+            }
+            else {
+                // updating protected note outside of protected session means we will keep original ciphertexts
+                delete pojo.title;
+            }
+        }
+
+        return pojo;
+    }
+}
+
+module.exports = BAttachment;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/backend_api/becca_entities_bblob.js.html b/docs/backend_api/becca_entities_bblob.js.html new file mode 100644 index 000000000..89a6fc446 --- /dev/null +++ b/docs/backend_api/becca_entities_bblob.js.html @@ -0,0 +1,81 @@ + + + + + JSDoc: Source: becca/entities/bblob.js + + + + + + + + + + +
+ +

Source: becca/entities/bblob.js

+ + + + + + +
+
+
class BBlob {
+    static get entityName() { return "blobs"; }
+    static get primaryKeyName() { return "blobId"; }
+    static get hashedProperties() { return ["blobId", "content"]; }
+
+    constructor(row) {
+        /** @type {string} */
+        this.blobId = row.blobId;
+        /** @type {string|Buffer} */
+        this.content = row.content;
+        /** @type {int} */
+        this.contentLength = row.contentLength;
+        /** @type {string} */
+        this.dateModified = row.dateModified;
+        /** @type {string} */
+        this.utcDateModified = row.utcDateModified;
+    }
+
+    getPojo() {
+        return {
+            blobId: this.blobId,
+            content: this.content,
+            contentLength: this.contentLength,
+            dateModified: this.dateModified,
+            utcDateModified: this.utcDateModified
+        };
+    }
+}
+
+module.exports = BBlob;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/backend_api/becca_entities_brevision.js.html b/docs/backend_api/becca_entities_brevision.js.html new file mode 100644 index 000000000..331e8cd54 --- /dev/null +++ b/docs/backend_api/becca_entities_brevision.js.html @@ -0,0 +1,203 @@ + + + + + JSDoc: Source: becca/entities/brevision.js + + + + + + + + + + +
+ +

Source: becca/entities/brevision.js

+ + + + + + +
+
+
"use strict";
+
+const protectedSessionService = require('../../services/protected_session');
+const utils = require('../../services/utils');
+const dateUtils = require('../../services/date_utils');
+const becca = require('../becca');
+const AbstractBeccaEntity = require("./abstract_becca_entity");
+const sql = require("../../services/sql");
+const BAttachment = require("./battachment");
+
+/**
+ * Revision represents a snapshot of note's title and content at some point in the past.
+ * It's used for seamless note versioning.
+ *
+ * @extends AbstractBeccaEntity
+ */
+class BRevision extends AbstractBeccaEntity {
+    static get entityName() { return "revisions"; }
+    static get primaryKeyName() { return "revisionId"; }
+    static get hashedProperties() { return ["revisionId", "noteId", "title", "isProtected", "dateLastEdited", "dateCreated",
+                                            "utcDateLastEdited", "utcDateCreated", "utcDateModified", "blobId"]; }
+
+    constructor(row, titleDecrypted = false) {
+        super();
+
+        /** @type {string} */
+        this.revisionId = row.revisionId;
+        /** @type {string} */
+        this.noteId = row.noteId;
+        /** @type {string} */
+        this.type = row.type;
+        /** @type {string} */
+        this.mime = row.mime;
+        /** @type {boolean} */
+        this.isProtected = !!row.isProtected;
+        /** @type {string} */
+        this.title = row.title;
+        /** @type {string} */
+        this.blobId = row.blobId;
+        /** @type {string} */
+        this.dateLastEdited = row.dateLastEdited;
+        /** @type {string} */
+        this.dateCreated = row.dateCreated;
+        /** @type {string} */
+        this.utcDateLastEdited = row.utcDateLastEdited;
+        /** @type {string} */
+        this.utcDateCreated = row.utcDateCreated;
+        /** @type {string} */
+        this.utcDateModified = row.utcDateModified;
+        /** @type {int} */
+        this.contentLength = row.contentLength;
+
+        if (this.isProtected && !titleDecrypted) {
+            this.title = protectedSessionService.isProtectedSessionAvailable()
+                ? protectedSessionService.decryptString(this.title)
+                : "[protected]";
+        }
+    }
+
+    getNote() {
+        return becca.notes[this.noteId];
+    }
+
+    /** @returns {boolean} true if the note has string content (not binary) */
+    hasStringContent() {
+        return utils.isStringNote(this.type, this.mime);
+    }
+
+    isContentAvailable() {
+        return !this.revisionId // new note which was not encrypted yet
+            || !this.isProtected
+            || protectedSessionService.isProtectedSessionAvailable()
+    }
+
+    /*
+     * Note revision content has quite special handling - it's not a separate entity, but a lazily loaded
+     * part of Revision entity with its own sync. The reason behind this hybrid design is that
+     * content can be quite large, and it's not necessary to load it / fill memory for any note access even
+     * if we don't need a content, especially for bulk operations like search.
+     *
+     * This is the same approach as is used for Note's content.
+     */
+
+    /** @returns {string|Buffer} */
+    getContent() {
+        return this._getContent();
+    }
+
+    /**
+     * @param content
+     * @param {object} [opts]
+     * @param {object} [opts.forceSave=false] - will also save this BRevision entity
+     */
+    setContent(content, opts) {
+        this._setContent(content, opts);
+    }
+
+    /** @returns {BAttachment[]} */
+    getAttachments() {
+        return sql.getRows(`
+                SELECT attachments.*
+                FROM attachments 
+                WHERE ownerId = ? 
+                  AND isDeleted = 0`, [this.revisionId])
+            .map(row => new BAttachment(row));
+    }
+
+    beforeSaving() {
+        super.beforeSaving();
+
+        this.utcDateModified = dateUtils.utcNowDateTime();
+    }
+
+    getPojo() {
+        return {
+            revisionId: this.revisionId,
+            noteId: this.noteId,
+            type: this.type,
+            mime: this.mime,
+            isProtected: this.isProtected,
+            title: this.title,
+            blobId: this.blobId,
+            dateLastEdited: this.dateLastEdited,
+            dateCreated: this.dateCreated,
+            utcDateLastEdited: this.utcDateLastEdited,
+            utcDateCreated: this.utcDateCreated,
+            utcDateModified: this.utcDateModified,
+            content: this.content, // used when retrieving full note revision to frontend
+            contentLength: this.contentLength
+        };
+    }
+
+    getPojoToSave() {
+        const pojo = this.getPojo();
+        delete pojo.content; // not getting persisted
+        delete pojo.contentLength; // not getting persisted
+
+        if (pojo.isProtected) {
+            if (protectedSessionService.isProtectedSessionAvailable()) {
+                pojo.title = protectedSessionService.encrypt(this.title);
+            }
+            else {
+                // updating protected note outside of protected session means we will keep original ciphertexts
+                delete pojo.title;
+            }
+        }
+
+        return pojo;
+    }
+}
+
+module.exports = BRevision;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/frontend_api/entities_fattachment.js.html b/docs/frontend_api/entities_fattachment.js.html new file mode 100644 index 000000000..b2137c353 --- /dev/null +++ b/docs/frontend_api/entities_fattachment.js.html @@ -0,0 +1,95 @@ + + + + + JSDoc: Source: entities/fattachment.js + + + + + + + + + + +
+ +

Source: entities/fattachment.js

+ + + + + + +
+
+
class FAttachment {
+    constructor(froca, row) {
+        /** @type {Froca} */
+        this.froca = froca;
+
+        this.update(row);
+    }
+
+    update(row) {
+        /** @type {string} */
+        this.attachmentId = row.attachmentId;
+        /** @type {string} */
+        this.ownerId = row.ownerId;
+        /** @type {string} */
+        this.role = row.role;
+        /** @type {string} */
+        this.mime = row.mime;
+        /** @type {string} */
+        this.title = row.title;
+        /** @type {string} */
+        this.dateModified = row.dateModified;
+        /** @type {string} */
+        this.utcDateModified = row.utcDateModified;
+        /** @type {string} */
+        this.utcDateScheduledForErasureSince = row.utcDateScheduledForErasureSince;
+
+        /** @type {int} optionally added to the entity */
+        this.contentLength = row.contentLength;
+
+        this.froca.attachments[this.attachmentId] = this;
+    }
+
+    /** @returns {FNote} */
+    getNote() {
+        return this.froca.notes[this.ownerId];
+    }
+
+    /** @return {FBlob} */
+    async getBlob() {
+        return await this.froca.getBlob('attachments', this.attachmentId);
+    }
+}
+
+export default FAttachment;
+
+
+
+ + + + +
+ + + +
+ + + + + + + diff --git a/docs/frontend_api/entities_fblob.js.html b/docs/frontend_api/entities_fblob.js.html new file mode 100644 index 000000000..311c1fe77 --- /dev/null +++ b/docs/frontend_api/entities_fblob.js.html @@ -0,0 +1,69 @@ + + + + + JSDoc: Source: entities/fblob.js + + + + + + + + + + +
+ +

Source: entities/fblob.js

+ + + + + + +
+
+
export default class FBlob {
+    constructor(row) {
+        /** @type {string} */
+        this.blobId = row.blobId;
+
+        /**
+         * can either contain the whole content (in e.g. string notes), only part (large text notes) or nothing at all (binary notes, images)
+         * @type {string}
+         */
+        this.content = row.content;
+        this.contentLength = row.contentLength;
+
+        /** @type {string} */
+        this.dateModified = row.dateModified;
+        /** @type {string} */
+        this.utcDateModified = row.utcDateModified;
+    }
+}
+
+
+
+ + + + +
+ + + +
+ + + + + + +