Compare commits

..

7 Commits

Author SHA1 Message Date
Raito Bezarius 7a99913d0e feat(provider): add E2EESDKClientProvider wrapping the app
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-12 16:40:53 +02:00
Julien Bouquillon 980a18aff2 fix-ts 2024-09-12 16:31:03 +02:00
Julien Bouquillon 6f655a20ac wip 2024-09-12 16:26:04 +02:00
Julien Bouquillon 39d93e330e wip 2024-09-12 16:13:08 +02:00
Raito Bezarius cc2d034abf wip! wip! wip! auth for E2EE
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-12 15:51:12 +02:00
Raito Bezarius 312a92a8e0 feat(api,front): expose the sub OIDC field for the frontend
Useful for E2EE encryption identification.

Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
2024-09-12 15:51:12 +02:00
Anthony LC 7a6c0f0eee ♻️(frontend) save editor as json
Stop to save a y.js doc to save the json editor.
2024-09-12 15:20:55 +02:00
8 changed files with 20 additions and 67 deletions
-1
View File
@@ -148,7 +148,6 @@ class DocumentSerializer(BaseResourceSerializer):
"title",
"accesses",
"abilities",
"is_e2ee",
"link_role",
"link_reach",
"created_at",
@@ -1,18 +0,0 @@
# Generated by Django 5.1 on 2024-09-12 13:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0005_remove_document_is_public_alter_document_link_reach_and_more'),
]
operations = [
migrations.AddField(
model_name='document',
name='is_e2ee',
field=models.BooleanField(default=False),
),
]
-1
View File
@@ -329,7 +329,6 @@ class Document(BaseModel):
link_role = models.CharField(
max_length=20, choices=LinkRoleChoices.choices, default=LinkRoleChoices.READER
)
is_e2ee = models.BooleanField(default=False)
_content = None
@@ -33,7 +33,6 @@ def test_api_documents_retrieve_anonymous_public():
"versions_retrieve": False,
},
"accesses": [],
"is_e2ee": False,
"link_reach": "public",
"link_role": document.link_role,
"title": document.title,
@@ -88,7 +87,6 @@ def test_api_documents_retrieve_authenticated_unrelated_public_or_authenticated(
"versions_retrieve": False,
},
"accesses": [],
"is_e2ee": False,
"link_reach": reach,
"link_role": document.link_role,
"title": document.title,
@@ -196,7 +194,6 @@ def test_api_documents_retrieve_authenticated_related_direct():
"title": document.title,
"content": document.content,
"abilities": document.get_abilities(user),
"is_e2ee": False,
"link_reach": document.link_reach,
"link_role": document.link_role,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
@@ -335,7 +332,6 @@ def test_api_documents_retrieve_authenticated_related_team_members(
"title": document.title,
"content": document.content,
"abilities": document.get_abilities(user),
"is_e2ee": False,
"link_reach": "restricted",
"link_role": document.link_role,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
@@ -456,7 +452,6 @@ def test_api_documents_retrieve_authenticated_related_team_administrators(
"title": document.title,
"content": document.content,
"abilities": document.get_abilities(user),
"is_e2ee": False,
"link_reach": "restricted",
"link_role": document.link_role,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
@@ -581,7 +576,6 @@ def test_api_documents_retrieve_authenticated_related_team_owners(
"title": document.title,
"content": document.content,
"abilities": document.get_abilities(user),
"is_e2ee": False,
"link_reach": "restricted",
"link_role": document.link_role,
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
@@ -1,4 +1,4 @@
import { Block, BlockNoteEditor as BlockNoteEditorCore, PartialBlock } from '@blocknote/core';
import { Block, BlockNoteEditor as BlockNoteEditorCore } from '@blocknote/core';
import '@blocknote/core/fonts/inter.css';
import { BlockNoteView } from '@blocknote/mantine';
import '@blocknote/mantine/style.css';
@@ -104,25 +104,19 @@ export const BlockNoteContent = ({
// TODO decrypt doc.content
//localStorage.getItem('KEY');
const docId = doc.id;
const purpose = `docs:${docId}`;
const docId = 'uuid-du-doc';
const purpose = `doc:${docId}`;
const key = e2eClient.findKeyByPurpose(purpose);
console.log('purpose', purpose, 'key', key);
let plaintextContent: Array<PartialBlock> | undefined;
if (!key) {
alert('probleme de key');
return;
// return;
} else {
if (doc.content) {
plaintextContent = JSON.parse(e2eClient.decrypt(
doc.content,
key.keychainFingerprint,
) as string) as Array<PartialBlock>;
const decryptedMessage = e2eClient.decrypt(
doc.content,
key.keychainFingerprint,
);
console.log('decryptedMessage', plaintextContent);
} else {
plaintextContent = undefined;
}
console.log('decryptedMessage', decryptedMessage);
}
return BlockNoteEditorCore.create({
@@ -135,11 +129,10 @@ export const BlockNoteContent = ({
// },
// },
uploadFile,
initialContent: plaintextContent,
initialContent: JSON.parse(doc.content),
});
}, [doc.content, storedEditor, uploadFile]);
console.log("useSaveDoc", doc.id, provider.document, canSave, editor);
useSaveDoc(doc.id, provider.document, canSave, editor);
useEffect(() => {
@@ -20,11 +20,11 @@ const useSaveDoc = (
});
const e2eClient = useE2ESDKClient();
const [initialDoc, setInitialDoc] = useState<string>(
JSON.stringify(editor.document)
toBase64(Y.encodeStateAsUpdate(doc)),
);
useEffect(() => {
setInitialDoc(JSON.stringify(editor.document));
setInitialDoc(toBase64(Y.encodeStateAsUpdate(doc)));
}, [doc]);
/**
@@ -40,7 +40,7 @@ const useSaveDoc = (
transaction: Y.Transaction,
) => {
if (!transaction.local) {
setInitialDoc(JSON.stringify(editor.document));
setInitialDoc(toBase64(Y.encodeStateAsUpdate(updatedDoc)));
}
};
@@ -55,11 +55,11 @@ const useSaveDoc = (
* Check if the doc has been updated and can be saved.
*/
const hasChanged = useCallback(() => {
return initialDoc !== JSON.stringify(editor.document);
const newDoc = toBase64(Y.encodeStateAsUpdate(doc));
return initialDoc !== newDoc;
}, [doc, initialDoc]);
const shouldSave = useCallback(() => {
console.log('hasChanged', hasChanged(), 'canSave', canSave);
return hasChanged() && canSave;
}, [canSave, hasChanged]);
@@ -69,9 +69,9 @@ const useSaveDoc = (
// TODO encode the content
const purpose = `docs:${docId}`;
const docId = 'uuid-du-doc';
const purpose = `doc:${docId}`;
const key = e2eClient.findKeyByPurpose(purpose);
console.log("purpose", purpose, "key", key);
if (!key) {
alert('probleme de key');
return;
@@ -87,7 +87,7 @@ const useSaveDoc = (
updateDoc({
id: docId,
content: encrypted,
content: newDoc,
});
}, [docId, editor?.document, updateDoc]);
@@ -100,12 +100,10 @@ const useSaveDoc = (
}
const onSave = (e?: Event) => {
console.log('entered onSave');
if (!shouldSave()) {
return;
}
console.log('will save');
saveDoc();
/**
@@ -124,7 +122,7 @@ const useSaveDoc = (
};
// Save every minute
timeout.current = setInterval(onSave, 1000);
timeout.current = setInterval(onSave, 60000);
// Save when the user leaves the page
addEventListener('beforeunload', onSave);
// Save when the user navigates to another page
@@ -1,5 +1,4 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { e2esdkClient } from '@/core/auth/useAuthStore';
import { APIError, errorCauses, fetchAPI } from '@/api';
@@ -14,7 +13,6 @@ export const createDoc = async ({ title }: CreateDocParam): Promise<Doc> => {
method: 'POST',
body: JSON.stringify({
title,
is_e2ee: true
}),
});
@@ -22,16 +20,7 @@ export const createDoc = async ({ title }: CreateDocParam): Promise<Doc> => {
throw new APIError('Failed to create the doc', await errorCauses(response));
}
const resp = await (response.json() as Promise<Doc>);
const { keychainFingerprint } = await e2esdkClient.createNewKeychain(
`docs:${resp.id}`,
'secretBox'
);
console.log('new e2ee keychain registered', keychainFingerprint);
return resp;
return response.json() as Promise<Doc>;
};
interface CreateDocProps {
@@ -37,7 +37,6 @@ export interface Doc {
accesses: Access[];
created_at: string;
updated_at: string;
is_e2ee: boolean;
abilities: {
destroy: boolean;
link_configuration: boolean;