mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	split out note's content into separate entity, WIP
This commit is contained in:
		| @@ -16,586 +16,671 @@ | ||||
|     <table id="8" parent="2" name="branches"/> | ||||
|     <table id="9" parent="2" name="event_log"/> | ||||
|     <table id="10" parent="2" name="links"/> | ||||
|     <table id="11" parent="2" name="note_revisions"/> | ||||
|     <table id="12" parent="2" name="notes"/> | ||||
|     <table id="13" parent="2" name="options"/> | ||||
|     <table id="14" parent="2" name="recent_notes"/> | ||||
|     <table id="15" parent="2" name="source_ids"/> | ||||
|     <table id="16" parent="2" name="sqlite_master"> | ||||
|     <table id="11" parent="2" name="note_contents"/> | ||||
|     <table id="12" parent="2" name="note_revisions"/> | ||||
|     <table id="13" parent="2" name="notes"/> | ||||
|     <table id="14" parent="2" name="options"/> | ||||
|     <table id="15" parent="2" name="recent_notes"/> | ||||
|     <table id="16" parent="2" name="source_ids"/> | ||||
|     <table id="17" parent="2" name="sqlite_master"> | ||||
|       <System>1</System> | ||||
|     </table> | ||||
|     <table id="17" parent="2" name="sqlite_sequence"> | ||||
|     <table id="18" parent="2" name="sqlite_sequence"> | ||||
|       <System>1</System> | ||||
|     </table> | ||||
|     <table id="18" parent="2" name="sync"/> | ||||
|     <column id="19" parent="6" name="apiTokenId"> | ||||
|     <table id="19" parent="2" name="sync"/> | ||||
|     <column id="20" parent="6" name="apiTokenId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="20" parent="6" name="token"> | ||||
|     <column id="21" parent="6" name="token"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="21" parent="6" name="dateCreated"> | ||||
|     <column id="22" parent="6" name="dateCreated"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="22" parent="6" name="isDeleted"> | ||||
|     <column id="23" parent="6" name="isDeleted"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="23" parent="6" name="hash"> | ||||
|     <column id="24" parent="6" name="hash"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <index id="24" parent="6" name="sqlite_autoindex_api_tokens_1"> | ||||
|     <index id="25" parent="6" name="sqlite_autoindex_api_tokens_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>apiTokenId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="25" parent="6"> | ||||
|     <key id="26" parent="6"> | ||||
|       <ColNames>apiTokenId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_api_tokens_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="26" parent="7" name="attributeId"> | ||||
|     <column id="27" parent="7" name="attributeId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="27" parent="7" name="noteId"> | ||||
|     <column id="28" parent="7" name="noteId"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="28" parent="7" name="type"> | ||||
|     <column id="29" parent="7" name="type"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="29" parent="7" name="name"> | ||||
|     <column id="30" parent="7" name="name"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="30" parent="7" name="value"> | ||||
|     <column id="31" parent="7" name="value"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>''</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="31" parent="7" name="position"> | ||||
|     <column id="32" parent="7" name="position"> | ||||
|       <Position>6</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="32" parent="7" name="dateCreated"> | ||||
|     <column id="33" parent="7" name="dateCreated"> | ||||
|       <Position>7</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="33" parent="7" name="dateModified"> | ||||
|     <column id="34" parent="7" name="dateModified"> | ||||
|       <Position>8</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="34" parent="7" name="isDeleted"> | ||||
|     <column id="35" parent="7" name="isDeleted"> | ||||
|       <Position>9</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="35" parent="7" name="hash"> | ||||
|     <column id="36" parent="7" name="hash"> | ||||
|       <Position>10</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="36" parent="7" name="isInheritable"> | ||||
|     <column id="37" parent="7" name="isInheritable"> | ||||
|       <Position>11</Position> | ||||
|       <DataType>int|0s</DataType> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <index id="37" parent="7" name="sqlite_autoindex_attributes_1"> | ||||
|     <index id="38" parent="7" name="sqlite_autoindex_attributes_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>attributeId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="38" parent="7"> | ||||
|     <index id="39" parent="7" name="IDX_attributes_noteId"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="40" parent="7" name="IDX_attributes_noteId_index"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="41" parent="7" name="IDX_attributes_name_value"> | ||||
|       <ColNames>name | ||||
| value</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="42" parent="7" name="IDX_attributes_name"> | ||||
|       <ColNames>name</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="43" parent="7" name="IDX_attributes_name_index"> | ||||
|       <ColNames>name</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="44" parent="7" name="IDX_attributes_value"> | ||||
|       <ColNames>value</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="45" parent="7" name="IDX_attributes_value_index"> | ||||
|       <ColNames>value</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="46" parent="7"> | ||||
|       <ColNames>attributeId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_attributes_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="39" parent="8" name="branchId"> | ||||
|     <column id="47" parent="8" name="branchId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="40" parent="8" name="noteId"> | ||||
|     <column id="48" parent="8" name="noteId"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="41" parent="8" name="parentNoteId"> | ||||
|     <column id="49" parent="8" name="parentNoteId"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="42" parent="8" name="notePosition"> | ||||
|     <column id="50" parent="8" name="notePosition"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>INTEGER|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="43" parent="8" name="prefix"> | ||||
|     <column id="51" parent="8" name="prefix"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|     </column> | ||||
|     <column id="44" parent="8" name="isExpanded"> | ||||
|     <column id="52" parent="8" name="isExpanded"> | ||||
|       <Position>6</Position> | ||||
|       <DataType>BOOLEAN|0s</DataType> | ||||
|     </column> | ||||
|     <column id="45" parent="8" name="isDeleted"> | ||||
|     <column id="53" parent="8" name="isDeleted"> | ||||
|       <Position>7</Position> | ||||
|       <DataType>INTEGER|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="46" parent="8" name="dateModified"> | ||||
|     <column id="54" parent="8" name="dateModified"> | ||||
|       <Position>8</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="47" parent="8" name="hash"> | ||||
|     <column id="55" parent="8" name="hash"> | ||||
|       <Position>9</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="48" parent="8" name="dateCreated"> | ||||
|     <column id="56" parent="8" name="dateCreated"> | ||||
|       <Position>10</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression> | ||||
|     </column> | ||||
|     <index id="49" parent="8" name="sqlite_autoindex_branches_1"> | ||||
|     <index id="57" parent="8" name="sqlite_autoindex_branches_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>branchId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <index id="50" parent="8" name="IDX_branches_noteId_parentNoteId"> | ||||
|     <index id="58" parent="8" name="IDX_branches_noteId_parentNoteId"> | ||||
|       <ColNames>noteId | ||||
| parentNoteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="51" parent="8" name="IDX_branches_noteId"> | ||||
|     <index id="59" parent="8" name="IDX_branches_noteId"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="52" parent="8" name="IDX_branches_parentNoteId"> | ||||
|     <index id="60" parent="8" name="IDX_branches_parentNoteId"> | ||||
|       <ColNames>parentNoteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="53" parent="8"> | ||||
|     <key id="61" parent="8"> | ||||
|       <ColNames>branchId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_branches_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="54" parent="9" name="eventId"> | ||||
|     <column id="62" parent="9" name="eventId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="55" parent="9" name="noteId"> | ||||
|     <column id="63" parent="9" name="noteId"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|     </column> | ||||
|     <column id="56" parent="9" name="comment"> | ||||
|     <column id="64" parent="9" name="comment"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|     </column> | ||||
|     <column id="57" parent="9" name="dateCreated"> | ||||
|     <column id="65" parent="9" name="dateCreated"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <index id="58" parent="9" name="sqlite_autoindex_event_log_1"> | ||||
|     <index id="66" parent="9" name="sqlite_autoindex_event_log_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>eventId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="59" parent="9"> | ||||
|     <index id="67" parent="9" name="IDX_event_log_noteId"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="68" parent="9"> | ||||
|       <ColNames>eventId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_event_log_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="60" parent="10" name="linkId"> | ||||
|     <column id="69" parent="10" name="linkId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="61" parent="10" name="noteId"> | ||||
|     <column id="70" parent="10" name="noteId"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="62" parent="10" name="targetNoteId"> | ||||
|     <column id="71" parent="10" name="targetNoteId"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="63" parent="10" name="type"> | ||||
|     <column id="72" parent="10" name="type"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="64" parent="10" name="isDeleted"> | ||||
|     <column id="73" parent="10" name="hash"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>INTEGER|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="65" parent="10" name="dateCreated"> | ||||
|       <Position>6</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="66" parent="10" name="dateModified"> | ||||
|       <Position>7</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="67" parent="10" name="hash"> | ||||
|       <Position>8</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <index id="68" parent="10" name="sqlite_autoindex_links_1"> | ||||
|     <column id="74" parent="10" name="isDeleted"> | ||||
|       <Position>6</Position> | ||||
|       <DataType>INTEGER|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="75" parent="10" name="dateCreated"> | ||||
|       <Position>7</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="76" parent="10" name="dateModified"> | ||||
|       <Position>8</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <index id="77" parent="10" name="sqlite_autoindex_links_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>linkId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="69" parent="10"> | ||||
|     <index id="78" parent="10" name="IDX_links_noteId"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="79" parent="10" name="IDX_links_noteId_index"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="80" parent="10" name="IDX_links_targetNoteId"> | ||||
|       <ColNames>targetNoteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="81" parent="10" name="IDX_links_targetNoteId_index"> | ||||
|       <ColNames>targetNoteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="82" parent="10"> | ||||
|       <ColNames>linkId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_links_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="70" parent="11" name="noteRevisionId"> | ||||
|     <column id="83" parent="11" name="noteContentId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="71" parent="11" name="noteId"> | ||||
|     <column id="84" parent="11" name="noteId"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="72" parent="11" name="title"> | ||||
|     <column id="85" parent="11" name="isProtected"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="86" parent="11" name="content"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <DefaultExpression>NULL</DefaultExpression> | ||||
|     </column> | ||||
|     <index id="87" parent="11" name="sqlite_autoindex_note_contents_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>noteContentId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <index id="88" parent="11" name="IDX_note_contents_noteId"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="89" parent="11"> | ||||
|       <ColNames>noteContentId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_note_contents_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="90" parent="12" name="noteRevisionId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="91" parent="12" name="noteId"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="92" parent="12" name="title"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|     </column> | ||||
|     <column id="73" parent="11" name="content"> | ||||
|     <column id="93" parent="12" name="content"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|     </column> | ||||
|     <column id="74" parent="11" name="isProtected"> | ||||
|     <column id="94" parent="12" name="isProtected"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="75" parent="11" name="dateModifiedFrom"> | ||||
|     <column id="95" parent="12" name="dateModifiedFrom"> | ||||
|       <Position>6</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="76" parent="11" name="dateModifiedTo"> | ||||
|     <column id="96" parent="12" name="dateModifiedTo"> | ||||
|       <Position>7</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="77" parent="11" name="type"> | ||||
|     <column id="97" parent="12" name="type"> | ||||
|       <Position>8</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>''</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="78" parent="11" name="mime"> | ||||
|     <column id="98" parent="12" name="mime"> | ||||
|       <Position>9</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>''</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="79" parent="11" name="hash"> | ||||
|     <column id="99" parent="12" name="hash"> | ||||
|       <Position>10</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <index id="80" parent="11" name="sqlite_autoindex_note_revisions_1"> | ||||
|     <index id="100" parent="12" name="sqlite_autoindex_note_revisions_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>noteRevisionId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <index id="81" parent="11" name="IDX_note_revisions_noteId"> | ||||
|     <index id="101" parent="12" name="IDX_note_revisions_noteId"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="82" parent="11" name="IDX_note_revisions_dateModifiedFrom"> | ||||
|     <index id="102" parent="12" name="IDX_note_revisions_dateModifiedFrom"> | ||||
|       <ColNames>dateModifiedFrom</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <index id="83" parent="11" name="IDX_note_revisions_dateModifiedTo"> | ||||
|     <index id="103" parent="12" name="IDX_note_revisions_dateModifiedTo"> | ||||
|       <ColNames>dateModifiedTo</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="84" parent="11"> | ||||
|     <key id="104" parent="12"> | ||||
|       <ColNames>noteRevisionId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_note_revisions_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="85" parent="12" name="noteId"> | ||||
|     <column id="105" parent="13" name="noteId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="86" parent="12" name="title"> | ||||
|     <column id="106" parent="13" name="title"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>"note"</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="87" parent="12" name="content"> | ||||
|     <column id="107" parent="13" name="isProtected"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <DefaultExpression>NULL</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="88" parent="12" name="isProtected"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="89" parent="12" name="type"> | ||||
|       <Position>5</Position> | ||||
|     <column id="108" parent="13" name="type"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>'text'</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="90" parent="12" name="mime"> | ||||
|       <Position>6</Position> | ||||
|     <column id="109" parent="13" name="mime"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>'text/html'</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="91" parent="12" name="hash"> | ||||
|       <Position>7</Position> | ||||
|     <column id="110" parent="13" name="hash"> | ||||
|       <Position>6</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="92" parent="12" name="isDeleted"> | ||||
|       <Position>8</Position> | ||||
|     <column id="111" parent="13" name="isDeleted"> | ||||
|       <Position>7</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="93" parent="12" name="dateCreated"> | ||||
|     <column id="112" parent="13" name="dateCreated"> | ||||
|       <Position>8</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="113" parent="13" name="dateModified"> | ||||
|       <Position>9</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="94" parent="12" name="dateModified"> | ||||
|       <Position>10</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <index id="95" parent="12" name="sqlite_autoindex_notes_1"> | ||||
|     <index id="114" parent="13" name="sqlite_autoindex_notes_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="96" parent="12"> | ||||
|     <index id="115" parent="13" name="IDX_notes_isDeleted"> | ||||
|       <ColNames>isDeleted</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="116" parent="13"> | ||||
|       <ColNames>noteId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_notes_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="97" parent="13" name="name"> | ||||
|     <column id="117" parent="14" name="name"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="98" parent="13" name="value"> | ||||
|     <column id="118" parent="14" name="value"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|     </column> | ||||
|     <column id="99" parent="13" name="dateModified"> | ||||
|     <column id="119" parent="14" name="dateModified"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|     </column> | ||||
|     <column id="100" parent="13" name="isSynced"> | ||||
|     <column id="120" parent="14" name="isSynced"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>INTEGER|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>0</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="101" parent="13" name="hash"> | ||||
|     <column id="121" parent="14" name="hash"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="102" parent="13" name="dateCreated"> | ||||
|     <column id="122" parent="14" name="dateCreated"> | ||||
|       <Position>6</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>'1970-01-01T00:00:00.000Z'</DefaultExpression> | ||||
|     </column> | ||||
|     <index id="103" parent="13" name="sqlite_autoindex_options_1"> | ||||
|     <index id="123" parent="14" name="sqlite_autoindex_options_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>name</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="104" parent="13"> | ||||
|     <key id="124" parent="14"> | ||||
|       <ColNames>name</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_options_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="105" parent="14" name="branchId"> | ||||
|     <column id="125" parent="15" name="branchId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="106" parent="14" name="notePath"> | ||||
|     <column id="126" parent="15" name="notePath"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="107" parent="14" name="hash"> | ||||
|     <column id="127" parent="15" name="hash"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <DefaultExpression>""</DefaultExpression> | ||||
|     </column> | ||||
|     <column id="108" parent="14" name="dateCreated"> | ||||
|     <column id="128" parent="15" name="dateCreated"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="109" parent="14" name="isDeleted"> | ||||
|     <column id="129" parent="15" name="isDeleted"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>INT|0s</DataType> | ||||
|     </column> | ||||
|     <index id="110" parent="14" name="sqlite_autoindex_recent_notes_1"> | ||||
|     <index id="130" parent="15" name="sqlite_autoindex_recent_notes_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>branchId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="111" parent="14"> | ||||
|     <key id="131" parent="15"> | ||||
|       <ColNames>branchId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_recent_notes_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="112" parent="15" name="sourceId"> | ||||
|     <column id="132" parent="16" name="sourceId"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="113" parent="15" name="dateCreated"> | ||||
|     <column id="133" parent="16" name="dateCreated"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <index id="114" parent="15" name="sqlite_autoindex_source_ids_1"> | ||||
|     <index id="134" parent="16" name="sqlite_autoindex_source_ids_1"> | ||||
|       <NameSurrogate>1</NameSurrogate> | ||||
|       <ColNames>sourceId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <key id="115" parent="15"> | ||||
|     <key id="135" parent="16"> | ||||
|       <ColNames>sourceId</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|       <UnderlyingIndexName>sqlite_autoindex_source_ids_1</UnderlyingIndexName> | ||||
|     </key> | ||||
|     <column id="116" parent="16" name="type"> | ||||
|     <column id="136" parent="17" name="type"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>text|0s</DataType> | ||||
|     </column> | ||||
|     <column id="117" parent="16" name="name"> | ||||
|     <column id="137" parent="17" name="name"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>text|0s</DataType> | ||||
|     </column> | ||||
|     <column id="118" parent="16" name="tbl_name"> | ||||
|     <column id="138" parent="17" name="tbl_name"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>text|0s</DataType> | ||||
|     </column> | ||||
|     <column id="119" parent="16" name="rootpage"> | ||||
|     <column id="139" parent="17" name="rootpage"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>integer|0s</DataType> | ||||
|     </column> | ||||
|     <column id="120" parent="16" name="sql"> | ||||
|     <column id="140" parent="17" name="sql"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>text|0s</DataType> | ||||
|     </column> | ||||
|     <column id="121" parent="17" name="name"> | ||||
|     <column id="141" parent="18" name="name"> | ||||
|       <Position>1</Position> | ||||
|     </column> | ||||
|     <column id="122" parent="17" name="seq"> | ||||
|     <column id="142" parent="18" name="seq"> | ||||
|       <Position>2</Position> | ||||
|     </column> | ||||
|     <column id="123" parent="18" name="id"> | ||||
|     <column id="143" parent="19" name="id"> | ||||
|       <Position>1</Position> | ||||
|       <DataType>INTEGER|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|       <SequenceIdentity>1</SequenceIdentity> | ||||
|     </column> | ||||
|     <column id="124" parent="18" name="entityName"> | ||||
|     <column id="144" parent="19" name="entityName"> | ||||
|       <Position>2</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="125" parent="18" name="entityId"> | ||||
|     <column id="145" parent="19" name="entityId"> | ||||
|       <Position>3</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="126" parent="18" name="sourceId"> | ||||
|     <column id="146" parent="19" name="sourceId"> | ||||
|       <Position>4</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <column id="127" parent="18" name="syncDate"> | ||||
|     <column id="147" parent="19" name="syncDate"> | ||||
|       <Position>5</Position> | ||||
|       <DataType>TEXT|0s</DataType> | ||||
|       <NotNull>1</NotNull> | ||||
|     </column> | ||||
|     <index id="128" parent="18" name="IDX_sync_entityName_entityId"> | ||||
|     <index id="148" parent="19" name="IDX_sync_entityName_entityId"> | ||||
|       <ColNames>entityName | ||||
| entityId</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|       <Unique>1</Unique> | ||||
|     </index> | ||||
|     <index id="129" parent="18" name="IDX_sync_syncDate"> | ||||
|     <index id="149" parent="19" name="IDX_sync_syncDate"> | ||||
|       <ColNames>syncDate</ColNames> | ||||
|       <ColumnCollations></ColumnCollations> | ||||
|     </index> | ||||
|     <key id="130" parent="18"> | ||||
|     <key id="150" parent="19"> | ||||
|       <ColNames>id</ColNames> | ||||
|       <Primary>1</Primary> | ||||
|     </key> | ||||
|   | ||||
							
								
								
									
										34
									
								
								db/migrations/0125__create_note_content_table.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								db/migrations/0125__create_note_content_table.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| CREATE TABLE IF NOT EXISTS "note_contents" ( | ||||
|   `noteContentId`	TEXT NOT NULL, | ||||
|   `noteId`	TEXT NOT NULL, | ||||
|   `isProtected`	INT NOT NULL DEFAULT 0, | ||||
|   `content`	TEXT NULL DEFAULT NULL, | ||||
|   PRIMARY KEY(`noteContentId`) | ||||
| ); | ||||
|  | ||||
| CREATE UNIQUE INDEX `IDX_note_contents_noteId` ON `note_contents` (`noteId`); | ||||
|  | ||||
| INSERT INTO note_contents (noteContentId, noteId, isProtected, content) | ||||
|   SELECT 'C' || SUBSTR(noteId, 2), noteId, isProtected, content FROM notes; | ||||
|  | ||||
| CREATE TABLE IF NOT EXISTS "notes_mig" ( | ||||
|   `noteId`	TEXT NOT NULL, | ||||
|   `title`	TEXT NOT NULL DEFAULT "note", | ||||
|   `isProtected`	INT NOT NULL DEFAULT 0, | ||||
|   `type` TEXT NOT NULL DEFAULT 'text', | ||||
|   `mime` TEXT NOT NULL DEFAULT 'text/html', | ||||
|   `hash` TEXT DEFAULT "" NOT NULL, | ||||
|   `isDeleted`	INT NOT NULL DEFAULT 0, | ||||
|   `dateCreated`	TEXT NOT NULL, | ||||
|   `dateModified`	TEXT NOT NULL, | ||||
|   PRIMARY KEY(`noteId`) | ||||
| ); | ||||
|  | ||||
| INSERT INTO notes_mig (noteId, title, isProtected, isDeleted, dateCreated, dateModified, type, mime, hash) | ||||
| SELECT noteId, title, isProtected, isDeleted, dateCreated, dateModified, type, mime, hash FROM notes; | ||||
|  | ||||
| DROP TABLE notes; | ||||
|  | ||||
| ALTER TABLE notes_mig RENAME TO notes; | ||||
|  | ||||
| CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`); | ||||
							
								
								
									
										8
									
								
								db/migrations/0126__create_missing_indexes.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								db/migrations/0126__create_missing_indexes.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| CREATE INDEX `IDX_attributes_noteId` ON `attributes` (`noteId`); | ||||
| CREATE INDEX `IDX_attributes_name` ON `attributes` (`name`); | ||||
| CREATE INDEX `IDX_attributes_value` ON `attributes` (`value`); | ||||
|  | ||||
| CREATE INDEX `IDX_event_log_noteId` ON `event_log` (`noteId`); | ||||
|  | ||||
| CREATE INDEX `IDX_links_noteId` ON `links` (`noteId`); | ||||
| CREATE INDEX `IDX_links_targetNoteId` ON `links` (`targetNoteId`); | ||||
| @@ -1,4 +1,5 @@ | ||||
| const Note = require('../entities/note'); | ||||
| const NoteContent = require('../entities/note_content'); | ||||
| const NoteRevision = require('../entities/note_revision'); | ||||
| const Link = require('../entities/link'); | ||||
| const Branch = require('../entities/branch'); | ||||
| @@ -12,6 +13,7 @@ const ENTITY_NAME_TO_ENTITY = { | ||||
|     "attributes": Attribute, | ||||
|     "branches": Branch, | ||||
|     "notes": Note, | ||||
|     "note_contents": NoteContent, | ||||
|     "note_revisions": NoteRevision, | ||||
|     "recent_notes": RecentNote, | ||||
|     "options": Option, | ||||
| @@ -48,6 +50,9 @@ function createEntityFromRow(row) { | ||||
|     else if (row.branchId) { | ||||
|         entity = new Branch(row); | ||||
|     } | ||||
|     else if (row.noteContentId) { | ||||
|         entity = new NoteContent(row); | ||||
|     } | ||||
|     else if (row.noteId) { | ||||
|         entity = new Note(row); | ||||
|     } | ||||
|   | ||||
| @@ -19,7 +19,6 @@ const RELATION_DEFINITION = 'relation-definition'; | ||||
|  * @property {string} type - one of "text", "code", "file" or "render" | ||||
|  * @property {string} mime - MIME type, e.g. "text/html" | ||||
|  * @property {string} title - note title | ||||
|  * @property {string} content - note content - e.g. HTML text for text notes, file payload for files | ||||
|  * @property {boolean} isProtected - true if note is protected | ||||
|  * @property {boolean} isDeleted - true if note is deleted | ||||
|  * @property {string} dateCreated | ||||
| @@ -30,7 +29,7 @@ const RELATION_DEFINITION = 'relation-definition'; | ||||
| class Note extends Entity { | ||||
|     static get entityName() { return "notes"; } | ||||
|     static get primaryKeyName() { return "noteId"; } | ||||
|     static get hashedProperties() { return ["noteId", "title", "content", "type", "isProtected", "isDeleted"]; } | ||||
|     static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted"]; } | ||||
|  | ||||
|     /** | ||||
|      * @param row - object containing database row from "notes" table | ||||
| @@ -54,26 +53,18 @@ class Note extends Entity { | ||||
|                 // saving ciphertexts in case we do want to update protected note outside of protected session | ||||
|                 // (which is allowed) | ||||
|                 this.titleCipherText = this.title; | ||||
|                 this.contentCipherText = this.content; | ||||
|  | ||||
|                 this.title = "[protected]"; | ||||
|                 this.content = ""; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         this.setContent(this.content); | ||||
|     /** @returns {Promise<NoteContent>} */ | ||||
|     async getNoteContent() { | ||||
|         if (!this.noteContent) { | ||||
|             this.noteContent = await repository.getEntity(`SELECT * FROM note_contents WHERE noteId = ?`, [this.noteId]); | ||||
|         } | ||||
|  | ||||
|     setContent(content) { | ||||
|         this.content = content; | ||||
|  | ||||
|         // if parsing below is not successful then there's no jsonContent as opposed to still having the old unupdated ones | ||||
|         delete this.jsonContent; | ||||
|  | ||||
|         try { | ||||
|             this.jsonContent = JSON.parse(this.content); | ||||
|         } | ||||
|         catch(e) {} | ||||
|         return this.noteContent; | ||||
|     } | ||||
|  | ||||
|     /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */ | ||||
|   | ||||
							
								
								
									
										82
									
								
								src/entities/note_content.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/entities/note_content.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const Entity = require('./entity'); | ||||
| const protectedSessionService = require('../services/protected_session'); | ||||
| const repository = require('../services/repository'); | ||||
|  | ||||
| /** | ||||
|  * This represents a Note which is a central object in the Trilium Notes project. | ||||
|  * | ||||
|  * @property {string} noteContentId - primary key | ||||
|  * @property {string} noteId - reference to owning note | ||||
|  * @property {boolean} isProtected - true if note content is protected | ||||
|  * @property {blob} content - note content - e.g. HTML text for text notes, file payload for files | ||||
|  * | ||||
|  * @extends Entity | ||||
|  */ | ||||
| class NoteContent extends Entity { | ||||
|     static get entityName() { | ||||
|         return "note_contents"; | ||||
|     } | ||||
|  | ||||
|     static get primaryKeyName() { | ||||
|         return "noteContentId"; | ||||
|     } | ||||
|  | ||||
|     static get hashedProperties() { | ||||
|         return ["noteContentId", "noteId", "isProtected", "content"]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param row - object containing database row from "note_contents" table | ||||
|      */ | ||||
|     constructor(row) { | ||||
|         super(row); | ||||
|  | ||||
|         this.isProtected = !!this.isProtected; | ||||
|         /* true if content (meaning any kind of potentially encrypted content) is either not encrypted | ||||
|          * or encrypted, but with available protected session (so effectively decrypted) */ | ||||
|         this.isContentAvailable = true; | ||||
|  | ||||
|         // check if there's noteContentId, otherwise this is a new entity which wasn't encrypted yet | ||||
|         if (this.isProtected && this.noteContentId) { | ||||
|             this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable(); | ||||
|  | ||||
|             if (this.isContentAvailable) { | ||||
|                 protectedSessionService.decryptNoteContent(this); | ||||
|             } | ||||
|             else { | ||||
|                 // saving ciphertexts in case we do want to update protected note outside of protected session | ||||
|                 // (which is allowed) | ||||
|                 this.contentCipherText = this.content; | ||||
|                 this.content = ""; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @returns {Promise<Note>} | ||||
|      */ | ||||
|     async getNote() { | ||||
|         return await repository.getNote(this.noteId); | ||||
|     } | ||||
|  | ||||
|     // cannot be static! | ||||
|     updatePojo(pojo) { | ||||
|         if (pojo.isProtected) { | ||||
|             if (this.isContentAvailable) { | ||||
|                 protectedSessionService.encryptNoteContent(pojo); | ||||
|             } | ||||
|             else { | ||||
|                 // updating protected note outside of protected session means we will keep original ciphertext | ||||
|                 pojo.content = pojo.contentCipherText; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         delete pojo.jsonContent; | ||||
|         delete pojo.isContentAvailable; | ||||
|         delete pojo.contentCipherText; | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = NoteContent; | ||||
| @@ -8,15 +8,15 @@ class NoteFull extends NoteShort { | ||||
|         super(treeCache, row); | ||||
|  | ||||
|         /** @param {string} */ | ||||
|         this.content = row.content; | ||||
|         this.noteContent = row.noteContent; | ||||
|  | ||||
|         if (this.content !== "" && this.isJson()) { | ||||
|             try { | ||||
|                 /** @param {object} */ | ||||
|                 this.jsonContent = JSON.parse(this.content); | ||||
|             } | ||||
|             catch(e) {} | ||||
|         } | ||||
|         // if (this.content !== "" && this.isJson()) { | ||||
|         //     try { | ||||
|         //         /** @param {object} */ | ||||
|         //         this.jsonContent = JSON.parse(this.content); | ||||
|         //     } | ||||
|         //     catch(e) {} | ||||
|         // } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -357,6 +357,7 @@ export default { | ||||
|     updateNoteView, | ||||
|     loadNote, | ||||
|     getCurrentNote, | ||||
|     getCurrentNoteContent, | ||||
|     getCurrentNoteType, | ||||
|     getCurrentNoteId, | ||||
|     focusOnTitle, | ||||
| @@ -364,7 +365,6 @@ export default { | ||||
|     saveNote, | ||||
|     saveNoteIfChanged, | ||||
|     noteChanged, | ||||
|     getCurrentNoteContent, | ||||
|     onNoteChange, | ||||
|     addDetailLoadedListener | ||||
| }; | ||||
| @@ -49,7 +49,7 @@ async function show() { | ||||
|     // this needs to happen after the element is shown, otherwise the editor won't be refreshed | ||||
|     // CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check) | ||||
|     // we provide fallback | ||||
|     codeEditor.setValue(currentNote.content || ""); | ||||
|     codeEditor.setValue(currentNote.noteContent.content || ""); | ||||
|  | ||||
|     const info = CodeMirror.findModeByMIME(currentNote.mime); | ||||
|  | ||||
|   | ||||
| @@ -27,8 +27,8 @@ async function show() { | ||||
|     $fileSize.text((attributeMap.fileSize || "?") + " bytes"); | ||||
|     $fileType.text(currentNote.mime); | ||||
|  | ||||
|     $previewRow.toggle(!!currentNote.content); | ||||
|     $previewContent.text(currentNote.content); | ||||
|     $previewRow.toggle(!!currentNote.noteContent.content); | ||||
|     $previewContent.text(currentNote.noteContent.content); | ||||
| } | ||||
|  | ||||
| $downloadButton.click(() => utils.download(getFileUrl())); | ||||
|   | ||||
| @@ -93,9 +93,9 @@ function loadMapData() { | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     if (currentNote.content) { | ||||
|     if (currentNote.noteContent.content) { | ||||
|         try { | ||||
|             mapData = JSON.parse(currentNote.content); | ||||
|             mapData = JSON.parse(currentNote.noteContent.content); | ||||
|         } catch (e) { | ||||
|             console.log("Could not parse content: ", e); | ||||
|         } | ||||
|   | ||||
| @@ -16,7 +16,7 @@ function show() { | ||||
|     $component.show(); | ||||
|  | ||||
|     try { | ||||
|         const json = JSON.parse(noteDetailService.getCurrentNote().content); | ||||
|         const json = JSON.parse(noteDetailService.getCurrentNote().noteContent.content); | ||||
|  | ||||
|         $searchString.val(json.searchString); | ||||
|     } | ||||
|   | ||||
| @@ -22,7 +22,7 @@ async function show() { | ||||
|  | ||||
|     textEditor.isReadOnly = await isReadOnly(); | ||||
|  | ||||
|     textEditor.setData(noteDetailService.getCurrentNote().content); | ||||
|     textEditor.setData(noteDetailService.getCurrentNote().noteContent.content); | ||||
|  | ||||
|     $component.show(); | ||||
| } | ||||
|   | ||||
| @@ -12,18 +12,10 @@ async function getNote(req) { | ||||
|         return [404, "Note " + noteId + " has not been found."]; | ||||
|     } | ||||
|  | ||||
|     if (note.type === 'file' || note.type === 'image') { | ||||
|         if (note.type === 'file' && note.mime.startsWith('text/')) { | ||||
|             note.content = note.content.toString("UTF-8"); | ||||
|     if (note.mime.startsWith('text/')) { | ||||
|         const noteContent = await note.getNoteContent(); | ||||
|  | ||||
|             if (note.content.length > 10000) { | ||||
|                 note.content = note.content.substr(0, 10000) + "..."; | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             // no need to transfer (potentially large) file/image payload for this request | ||||
|             note.content = null; | ||||
|         } | ||||
|         noteContent.content = noteContent.content.toString("UTF-8"); | ||||
|     } | ||||
|  | ||||
|     return note; | ||||
|   | ||||
| @@ -4,8 +4,8 @@ const build = require('./build'); | ||||
| const packageJson = require('../../package'); | ||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||
|  | ||||
| const APP_DB_VERSION = 124; | ||||
| const SYNC_VERSION = 4; | ||||
| const APP_DB_VERSION = 125; | ||||
| const SYNC_VERSION = 5; | ||||
|  | ||||
| module.exports = { | ||||
|     appVersion: packageJson.version, | ||||
|   | ||||
| @@ -234,6 +234,7 @@ async function findLogicIssues() { | ||||
|     await findIssues(` | ||||
|           SELECT noteId | ||||
|           FROM notes | ||||
|           JOIN note_contents USING(noteId) | ||||
|           WHERE | ||||
|             isDeleted = 0 | ||||
|             AND content IS NULL`, | ||||
|   | ||||
| @@ -47,28 +47,25 @@ function decryptNoteTitle(noteId, encryptedTitle) { | ||||
| } | ||||
|  | ||||
| function decryptNote(note) { | ||||
|     const dataKey = getDataKey(); | ||||
|  | ||||
|     if (!note.isProtected) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|     if (note.title) { | ||||
|             note.title = dataEncryptionService.decryptString(dataKey, note.title); | ||||
|         note.title = decryptNoteTitle(note.noteId) | ||||
|     } | ||||
| } | ||||
|  | ||||
|         if (note.content) { | ||||
|             if (note.type === 'file' || note.type === 'image') { | ||||
|                 note.content = dataEncryptionService.decrypt(dataKey, note.content); | ||||
|             } | ||||
|             else { | ||||
|                 note.content = dataEncryptionService.decryptString(dataKey, note.content); | ||||
|             } | ||||
| function decryptNoteContent(noteContent) { | ||||
|     if (!noteContent.isProtected) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|         noteContent.content = dataEncryptionService.decrypt(getDataKey(), noteContent.content); | ||||
|     } | ||||
|     catch (e) { | ||||
|         e.message = `Cannot decrypt note for noteId=${note.noteId}: ` + e.message; | ||||
|         e.message = `Cannot decrypt note content for noteContentId=${noteContent.noteContentId}: ` + e.message; | ||||
|         throw e; | ||||
|     } | ||||
| } | ||||
| @@ -96,10 +93,11 @@ function decryptNoteRevision(hist) { | ||||
| } | ||||
|  | ||||
| function encryptNote(note) { | ||||
|     const dataKey = getDataKey(); | ||||
|     note.title = dataEncryptionService.encrypt(getDataKey(), note.title); | ||||
| } | ||||
|  | ||||
|     note.title = dataEncryptionService.encrypt(dataKey, note.title); | ||||
|     note.content = dataEncryptionService.encrypt(dataKey, note.content); | ||||
| function encryptNoteContent(noteContent) { | ||||
|     noteContent.content = dataEncryptionService.encrypt(getDataKey(), noteContent.content); | ||||
| } | ||||
|  | ||||
| function encryptNoteRevision(revision) { | ||||
| @@ -115,9 +113,11 @@ module.exports = { | ||||
|     isProtectedSessionAvailable, | ||||
|     decryptNoteTitle, | ||||
|     decryptNote, | ||||
|     decryptNoteContent, | ||||
|     decryptNotes, | ||||
|     decryptNoteRevision, | ||||
|     encryptNote, | ||||
|     encryptNoteContent, | ||||
|     encryptNoteRevision, | ||||
|     setProtectedSessionId | ||||
| }; | ||||
| @@ -37,27 +37,32 @@ async function getEntity(query, params = []) { | ||||
|     return entityConstructor.createEntityFromRow(row); | ||||
| } | ||||
|  | ||||
| /** @returns {Note|null} */ | ||||
| /** @returns {Promise<Note|null>} */ | ||||
| async function getNote(noteId) { | ||||
|     return await getEntity("SELECT * FROM notes WHERE noteId = ?", [noteId]); | ||||
| } | ||||
|  | ||||
| /** @returns {Branch|null} */ | ||||
| /** @returns {Promise<NoteContent|null>} */ | ||||
| async function getNoteContent(noteContentId) { | ||||
|     return await getEntity("SELECT * FROM note_contents WHERE noteContentId = ?", [noteContentId]); | ||||
| } | ||||
|  | ||||
| /** @returns {Promise<Branch|null>} */ | ||||
| async function getBranch(branchId) { | ||||
|     return await getEntity("SELECT * FROM branches WHERE branchId = ?", [branchId]); | ||||
| } | ||||
|  | ||||
| /** @returns {Attribute|null} */ | ||||
| /** @returns {Promise<Attribute|null>} */ | ||||
| async function getAttribute(attributeId) { | ||||
|     return await getEntity("SELECT * FROM attributes WHERE attributeId = ?", [attributeId]); | ||||
| } | ||||
|  | ||||
| /** @returns {Option|null} */ | ||||
| /** @returns {Promise<Option|null>} */ | ||||
| async function getOption(name) { | ||||
|     return await getEntity("SELECT * FROM options WHERE name = ?", [name]); | ||||
| } | ||||
|  | ||||
| /** @returns {Link|null} */ | ||||
| /** @returns {Promise<Link|null>} */ | ||||
| async function getLink(linkId) { | ||||
|     return await getEntity("SELECT * FROM links WHERE linkId = ?", [linkId]); | ||||
| } | ||||
| @@ -121,6 +126,7 @@ module.exports = { | ||||
|     getEntities, | ||||
|     getEntity, | ||||
|     getNote, | ||||
|     getNoteContent, | ||||
|     getBranch, | ||||
|     getAttribute, | ||||
|     getOption, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user