mirror of
https://github.com/suitenumerique/docs.git
synced 2026-05-05 22:52:00 +02:00
Compare commits
7 Commits
config/inc
...
e2ee-hacka
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a99913d0e | ||
|
|
980a18aff2 | ||
|
|
6f655a20ac | ||
|
|
39d93e330e | ||
|
|
cc2d034abf | ||
|
|
312a92a8e0 | ||
|
|
7a6c0f0eee |
278
.github/workflows/impress.yml
vendored
278
.github/workflows/impress.yml
vendored
@@ -9,52 +9,52 @@ on:
|
|||||||
- "*"
|
- "*"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-git:
|
# lint-git:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'pull_request' # Makes sense only for pull requests
|
# if: github.event_name == 'pull_request' # Makes sense only for pull requests
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout repository
|
# - name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
# uses: actions/checkout@v2
|
||||||
with:
|
# with:
|
||||||
fetch-depth: 0
|
# fetch-depth: 0
|
||||||
- name: show
|
# - name: show
|
||||||
run: git log
|
# run: git log
|
||||||
- name: Enforce absence of print statements in code
|
# - name: Enforce absence of print statements in code
|
||||||
run: |
|
# run: |
|
||||||
! git diff origin/${{ github.event.pull_request.base.ref }}..HEAD -- . ':(exclude)**/impress.yml' | grep "print("
|
# ! git diff origin/${{ github.event.pull_request.base.ref }}..HEAD -- . ':(exclude)**/impress.yml' | grep "print("
|
||||||
- name: Check absence of fixup commits
|
# - name: Check absence of fixup commits
|
||||||
run: |
|
# run: |
|
||||||
! git log | grep 'fixup!'
|
# ! git log | grep 'fixup!'
|
||||||
- name: Install gitlint
|
# - name: Install gitlint
|
||||||
run: pip install --user requests gitlint
|
# run: pip install --user requests gitlint
|
||||||
- name: Lint commit messages added to main
|
# - name: Lint commit messages added to main
|
||||||
run: ~/.local/bin/gitlint --commits origin/${{ github.event.pull_request.base.ref }}..HEAD
|
# run: ~/.local/bin/gitlint --commits origin/${{ github.event.pull_request.base.ref }}..HEAD
|
||||||
|
|
||||||
check-changelog:
|
# check-changelog:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
if: |
|
# if: |
|
||||||
contains(github.event.pull_request.labels.*.name, 'noChangeLog') == false &&
|
# contains(github.event.pull_request.labels.*.name, 'noChangeLog') == false &&
|
||||||
github.event_name == 'pull_request'
|
# github.event_name == 'pull_request'
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout repository
|
# - name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
# uses: actions/checkout@v3
|
||||||
with:
|
# with:
|
||||||
fetch-depth: 50
|
# fetch-depth: 50
|
||||||
- name: Check that the CHANGELOG has been modified in the current branch
|
# - name: Check that the CHANGELOG has been modified in the current branch
|
||||||
run: git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.after }} | grep 'CHANGELOG.md'
|
# run: git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.after }} | grep 'CHANGELOG.md'
|
||||||
|
|
||||||
lint-changelog:
|
# lint-changelog:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout repository
|
# - name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
# uses: actions/checkout@v2
|
||||||
- name: Check CHANGELOG max line length
|
# - name: Check CHANGELOG max line length
|
||||||
run: |
|
# run: |
|
||||||
max_line_length=$(cat CHANGELOG.md | grep -Ev "^\[.*\]: https://github.com" | wc -L)
|
# max_line_length=$(cat CHANGELOG.md | grep -Ev "^\[.*\]: https://github.com" | wc -L)
|
||||||
if [ $max_line_length -ge 80 ]; then
|
# if [ $max_line_length -ge 80 ]; then
|
||||||
echo "ERROR: CHANGELOG has lines longer than 80 characters."
|
# echo "ERROR: CHANGELOG has lines longer than 80 characters."
|
||||||
exit 1
|
# exit 1
|
||||||
fi
|
# fi
|
||||||
|
|
||||||
build-mails:
|
build-mails:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -96,112 +96,112 @@ jobs:
|
|||||||
path: "src/backend/core/templates/mail"
|
path: "src/backend/core/templates/mail"
|
||||||
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
|
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
|
||||||
|
|
||||||
lint-back:
|
# lint-back:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
defaults:
|
# defaults:
|
||||||
run:
|
# run:
|
||||||
working-directory: src/backend
|
# working-directory: src/backend
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout repository
|
# - name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
# uses: actions/checkout@v2
|
||||||
- name: Install Python
|
# - name: Install Python
|
||||||
uses: actions/setup-python@v3
|
# uses: actions/setup-python@v3
|
||||||
with:
|
# with:
|
||||||
python-version: "3.10"
|
# python-version: "3.10"
|
||||||
- name: Install development dependencies
|
# - name: Install development dependencies
|
||||||
run: pip install --user .[dev]
|
# run: pip install --user .[dev]
|
||||||
- name: Check code formatting with ruff
|
# - name: Check code formatting with ruff
|
||||||
run: ~/.local/bin/ruff format . --diff
|
# run: ~/.local/bin/ruff format . --diff
|
||||||
- name: Lint code with ruff
|
# - name: Lint code with ruff
|
||||||
run: ~/.local/bin/ruff check .
|
# run: ~/.local/bin/ruff check .
|
||||||
- name: Lint code with pylint
|
# - name: Lint code with pylint
|
||||||
run: ~/.local/bin/pylint .
|
# run: ~/.local/bin/pylint .
|
||||||
|
|
||||||
test-back:
|
# test-back:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
needs: build-mails
|
# needs: build-mails
|
||||||
|
|
||||||
defaults:
|
# defaults:
|
||||||
run:
|
# run:
|
||||||
working-directory: src/backend
|
# working-directory: src/backend
|
||||||
|
|
||||||
services:
|
# services:
|
||||||
postgres:
|
# postgres:
|
||||||
image: postgres:16
|
# image: postgres:16
|
||||||
env:
|
# env:
|
||||||
POSTGRES_DB: impress
|
# POSTGRES_DB: impress
|
||||||
POSTGRES_USER: dinum
|
# POSTGRES_USER: dinum
|
||||||
POSTGRES_PASSWORD: pass
|
# POSTGRES_PASSWORD: pass
|
||||||
ports:
|
# ports:
|
||||||
- 5432:5432
|
# - 5432:5432
|
||||||
# needed because the postgres container does not provide a healthcheck
|
# # needed because the postgres container does not provide a healthcheck
|
||||||
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
# options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
||||||
|
|
||||||
env:
|
# env:
|
||||||
DJANGO_CONFIGURATION: Test
|
# DJANGO_CONFIGURATION: Test
|
||||||
DJANGO_SETTINGS_MODULE: impress.settings
|
# DJANGO_SETTINGS_MODULE: impress.settings
|
||||||
DJANGO_SECRET_KEY: ThisIsAnExampleKeyForTestPurposeOnly
|
# DJANGO_SECRET_KEY: ThisIsAnExampleKeyForTestPurposeOnly
|
||||||
OIDC_OP_JWKS_ENDPOINT: /endpoint-for-test-purpose-only
|
# OIDC_OP_JWKS_ENDPOINT: /endpoint-for-test-purpose-only
|
||||||
DB_HOST: localhost
|
# DB_HOST: localhost
|
||||||
DB_NAME: impress
|
# DB_NAME: impress
|
||||||
DB_USER: dinum
|
# DB_USER: dinum
|
||||||
DB_PASSWORD: pass
|
# DB_PASSWORD: pass
|
||||||
DB_PORT: 5432
|
# DB_PORT: 5432
|
||||||
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
|
# STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
|
||||||
AWS_S3_ENDPOINT_URL: http://localhost:9000
|
# AWS_S3_ENDPOINT_URL: http://localhost:9000
|
||||||
AWS_S3_ACCESS_KEY_ID: impress
|
# AWS_S3_ACCESS_KEY_ID: impress
|
||||||
AWS_S3_SECRET_ACCESS_KEY: password
|
# AWS_S3_SECRET_ACCESS_KEY: password
|
||||||
|
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout repository
|
# - name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
# uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Create writable /data
|
# - name: Create writable /data
|
||||||
run: |
|
# run: |
|
||||||
sudo mkdir -p /data/media && \
|
# sudo mkdir -p /data/media && \
|
||||||
sudo mkdir -p /data/static
|
# sudo mkdir -p /data/static
|
||||||
|
|
||||||
- name: Restore the mail templates
|
# - name: Restore the mail templates
|
||||||
uses: actions/cache@v4
|
# uses: actions/cache@v4
|
||||||
id: mail-templates
|
# id: mail-templates
|
||||||
with:
|
# with:
|
||||||
path: "src/backend/core/templates/mail"
|
# path: "src/backend/core/templates/mail"
|
||||||
key: mail-templates-${{ hashFiles('src/mail/mjml') }}
|
# key: mail-templates-${{ hashFiles('src/mail/mjml') }}
|
||||||
|
|
||||||
- name: Start Minio
|
# - name: Start Minio
|
||||||
run: |
|
# run: |
|
||||||
docker pull minio/minio
|
# docker pull minio/minio
|
||||||
docker run -d --name minio \
|
# docker run -d --name minio \
|
||||||
-p 9000:9000 \
|
# -p 9000:9000 \
|
||||||
-e "MINIO_ACCESS_KEY=impress" \
|
# -e "MINIO_ACCESS_KEY=impress" \
|
||||||
-e "MINIO_SECRET_KEY=password" \
|
# -e "MINIO_SECRET_KEY=password" \
|
||||||
-v /data/media:/data \
|
# -v /data/media:/data \
|
||||||
minio/minio server --console-address :9001 /data
|
# minio/minio server --console-address :9001 /data
|
||||||
|
|
||||||
- name: Configure MinIO
|
# - name: Configure MinIO
|
||||||
run: |
|
# run: |
|
||||||
MINIO=$(docker ps | grep minio/minio | sed -E 's/.*\s+([a-zA-Z0-9_-]+)$/\1/')
|
# MINIO=$(docker ps | grep minio/minio | sed -E 's/.*\s+([a-zA-Z0-9_-]+)$/\1/')
|
||||||
docker exec ${MINIO} sh -c \
|
# docker exec ${MINIO} sh -c \
|
||||||
"mc alias set impress http://localhost:9000 impress password && \
|
# "mc alias set impress http://localhost:9000 impress password && \
|
||||||
mc alias ls && \
|
# mc alias ls && \
|
||||||
mc mb impress/impress-media-storage && \
|
# mc mb impress/impress-media-storage && \
|
||||||
mc version enable impress/impress-media-storage"
|
# mc version enable impress/impress-media-storage"
|
||||||
|
|
||||||
- name: Install Python
|
# - name: Install Python
|
||||||
uses: actions/setup-python@v3
|
# uses: actions/setup-python@v3
|
||||||
with:
|
# with:
|
||||||
python-version: "3.10"
|
# python-version: "3.10"
|
||||||
|
|
||||||
- name: Install development dependencies
|
# - name: Install development dependencies
|
||||||
run: pip install --user .[dev]
|
# run: pip install --user .[dev]
|
||||||
|
|
||||||
- name: Install gettext (required to compile messages)
|
# - name: Install gettext (required to compile messages)
|
||||||
run: |
|
# run: |
|
||||||
sudo apt-get update
|
# sudo apt-get update
|
||||||
sudo apt-get install -y gettext pandoc
|
# sudo apt-get install -y gettext pandoc
|
||||||
|
|
||||||
- name: Generate a MO file from strings extracted from the project
|
# - name: Generate a MO file from strings extracted from the project
|
||||||
run: python manage.py compilemessages
|
# run: python manage.py compilemessages
|
||||||
|
|
||||||
- name: Run tests
|
# - name: Run tests
|
||||||
run: ~/.local/bin/pytest -n 2
|
# run: ~/.local/bin/pytest -n 2
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ class UserSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.User
|
model = models.User
|
||||||
fields = ["id", "email"]
|
fields = ["id", "sub", "email"]
|
||||||
read_only_fields = ["id", "email"]
|
read_only_fields = ["id", "sub", "email"]
|
||||||
|
|
||||||
|
|
||||||
class BaseAccessSerializer(serializers.ModelSerializer):
|
class BaseAccessSerializer(serializers.ModelSerializer):
|
||||||
|
|||||||
@@ -21,6 +21,9 @@
|
|||||||
"@gouvfr-lasuite/integration": "1.0.2",
|
"@gouvfr-lasuite/integration": "1.0.2",
|
||||||
"@hocuspocus/provider": "2.13.5",
|
"@hocuspocus/provider": "2.13.5",
|
||||||
"@openfun/cunningham-react": "2.9.4",
|
"@openfun/cunningham-react": "2.9.4",
|
||||||
|
"@socialgouv/e2esdk-client": "1.0.0-beta.28",
|
||||||
|
"@socialgouv/e2esdk-devtools": "1.0.0-beta.38",
|
||||||
|
"@socialgouv/e2esdk-react": "1.0.0-beta.28",
|
||||||
"@tanstack/react-query": "5.55.4",
|
"@tanstack/react-query": "5.55.4",
|
||||||
"i18next": "23.15.1",
|
"i18next": "23.15.1",
|
||||||
"idb": "8.0.0",
|
"idb": "8.0.0",
|
||||||
@@ -33,8 +36,8 @@
|
|||||||
"react-i18next": "15.0.1",
|
"react-i18next": "15.0.1",
|
||||||
"react-select": "5.8.0",
|
"react-select": "5.8.0",
|
||||||
"styled-components": "6.1.13",
|
"styled-components": "6.1.13",
|
||||||
"yjs": "*",
|
|
||||||
"y-protocols": "1.0.6",
|
"y-protocols": "1.0.6",
|
||||||
|
"yjs": "*",
|
||||||
"zustand": "4.5.5"
|
"zustand": "4.5.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { CunninghamProvider } from '@openfun/cunningham-react';
|
import { CunninghamProvider } from '@openfun/cunningham-react';
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import { E2ESDKClientProvider } from '@socialgouv/e2esdk-react';
|
||||||
|
import { e2esdkClient } from './auth/useAuthStore';
|
||||||
|
|
||||||
import { useCunninghamTheme } from '@/cunningham';
|
import { useCunninghamTheme } from '@/cunningham';
|
||||||
import '@/i18n/initI18n';
|
import '@/i18n/initI18n';
|
||||||
@@ -27,7 +29,9 @@ export function AppProvider({ children }: { children: React.ReactNode }) {
|
|||||||
return (
|
return (
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<CunninghamProvider theme={theme}>
|
<CunninghamProvider theme={theme}>
|
||||||
<Auth>{children}</Auth>
|
<E2ESDKClientProvider client={e2esdkClient}>
|
||||||
|
<Auth>{children}</Auth>
|
||||||
|
</E2ESDKClientProvider>
|
||||||
</CunninghamProvider>
|
</CunninghamProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
* Represents user retrieved from the API.
|
* Represents user retrieved from the API.
|
||||||
* @interface User
|
* @interface User
|
||||||
* @property {string} id - The id of the user.
|
* @property {string} id - The id of the user.
|
||||||
|
* @property {string} sub - The `sub` field of OIDC
|
||||||
* @property {string} email - The email of the user.
|
* @property {string} email - The email of the user.
|
||||||
* @property {string} name - The name of the user.
|
* @property {string} name - The name of the user.
|
||||||
*/
|
*/
|
||||||
export interface User {
|
export interface User {
|
||||||
id: string;
|
id: string;
|
||||||
|
sub: string;
|
||||||
email: string;
|
email: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,18 +5,31 @@ import { baseApiUrl } from '@/core/conf';
|
|||||||
import { User, getMe } from './api';
|
import { User, getMe } from './api';
|
||||||
import { PATH_AUTH_LOCAL_STORAGE } from './conf';
|
import { PATH_AUTH_LOCAL_STORAGE } from './conf';
|
||||||
|
|
||||||
|
import { Client, PublicUserIdentity } from '@socialgouv/e2esdk-client';
|
||||||
|
import { identity } from 'lodash';
|
||||||
|
|
||||||
|
export const e2esdkClient = new Client({
|
||||||
|
// Point it to where your server is listening
|
||||||
|
serverURL: 'https://app-a5a1b445-32e0-4cf4-a478-821a48f86ccf.cleverapps.io',
|
||||||
|
// Pass the signature public key you configured for the server
|
||||||
|
serverSignaturePublicKey: 'ayfva9SUh0mfgmifUtxcdLp4HriHJiqefEKnvYgY4qM',
|
||||||
|
});
|
||||||
|
|
||||||
interface AuthStore {
|
interface AuthStore {
|
||||||
initiated: boolean;
|
initiated: boolean;
|
||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
|
readyForEncryption: boolean;
|
||||||
initAuth: () => void;
|
initAuth: () => void;
|
||||||
logout: () => void;
|
logout: () => void;
|
||||||
login: () => void;
|
login: () => void;
|
||||||
|
endToEndData?: PublicUserIdentity;
|
||||||
userData?: User;
|
userData?: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
initiated: false,
|
initiated: false,
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
|
readyForEncryption: false,
|
||||||
userData: undefined,
|
userData: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -24,22 +37,51 @@ export const useAuthStore = create<AuthStore>((set) => ({
|
|||||||
initiated: initialState.initiated,
|
initiated: initialState.initiated,
|
||||||
authenticated: initialState.authenticated,
|
authenticated: initialState.authenticated,
|
||||||
userData: initialState.userData,
|
userData: initialState.userData,
|
||||||
|
readyForEncryption: initialState.readyForEncryption,
|
||||||
|
|
||||||
initAuth: () => {
|
initAuth: () => {
|
||||||
getMe()
|
getMe()
|
||||||
.then((data: User) => {
|
.then(
|
||||||
// If a path is stored in the local storage, we redirect to it
|
(data: User) => {
|
||||||
const path_auth = localStorage.getItem(PATH_AUTH_LOCAL_STORAGE);
|
// If a path is stored in the local storage, we redirect to it
|
||||||
if (path_auth) {
|
const path_auth = localStorage.getItem(PATH_AUTH_LOCAL_STORAGE);
|
||||||
localStorage.removeItem(PATH_AUTH_LOCAL_STORAGE);
|
if (path_auth) {
|
||||||
window.location.replace(path_auth);
|
localStorage.removeItem(PATH_AUTH_LOCAL_STORAGE);
|
||||||
return;
|
window.location.replace(path_auth);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
set({ authenticated: true, userData: data });
|
set({ authenticated: true, userData: data });
|
||||||
|
return e2esdkClient
|
||||||
|
.signup(data.sub)
|
||||||
|
.then(() => data)
|
||||||
|
.catch(() => data);
|
||||||
|
},
|
||||||
|
() => {},
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(data) => {
|
||||||
|
set({ readyForEncryption: true });
|
||||||
|
if (data) {
|
||||||
|
return e2esdkClient.login(data.sub);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
throw e;
|
||||||
|
//if (data) {
|
||||||
|
// return e2esdkClient.login(data.sub);
|
||||||
|
//}
|
||||||
|
//fail
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.then((publicIdentity: PublicUserIdentity | null | undefined) => {
|
||||||
|
if (!publicIdentity) throw Error('exploding');
|
||||||
|
console.log('publicIdentity', publicIdentity);
|
||||||
|
set({ endToEndData: publicIdentity });
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
console.log('finally');
|
||||||
set({ initiated: true });
|
set({ initiated: true });
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BlockNoteEditor as BlockNoteEditorCore } from '@blocknote/core';
|
import { Block, BlockNoteEditor as BlockNoteEditorCore } from '@blocknote/core';
|
||||||
import '@blocknote/core/fonts/inter.css';
|
import '@blocknote/core/fonts/inter.css';
|
||||||
import { BlockNoteView } from '@blocknote/mantine';
|
import { BlockNoteView } from '@blocknote/mantine';
|
||||||
import '@blocknote/mantine/style.css';
|
import '@blocknote/mantine/style.css';
|
||||||
@@ -17,6 +17,7 @@ import { useDocStore } from '../stores';
|
|||||||
import { randomColor } from '../utils';
|
import { randomColor } from '../utils';
|
||||||
|
|
||||||
import { BlockNoteToolbar } from './BlockNoteToolbar';
|
import { BlockNoteToolbar } from './BlockNoteToolbar';
|
||||||
|
import { useE2ESDKClient } from '@socialgouv/e2esdk-react';
|
||||||
|
|
||||||
const cssEditor = `
|
const cssEditor = `
|
||||||
&, & > .bn-container, & .ProseMirror {
|
&, & > .bn-container, & .ProseMirror {
|
||||||
@@ -71,7 +72,8 @@ export const BlockNoteContent = ({
|
|||||||
const { userData } = useAuthStore();
|
const { userData } = useAuthStore();
|
||||||
const { setStore, docsStore } = useDocStore();
|
const { setStore, docsStore } = useDocStore();
|
||||||
const canSave = doc.abilities.partial_update && !isVersion;
|
const canSave = doc.abilities.partial_update && !isVersion;
|
||||||
useSaveDoc(doc.id, provider.document, canSave);
|
|
||||||
|
const e2eClient = useE2ESDKClient();
|
||||||
const storedEditor = docsStore?.[storeId]?.editor;
|
const storedEditor = docsStore?.[storeId]?.editor;
|
||||||
const {
|
const {
|
||||||
mutateAsync: createDocAttachment,
|
mutateAsync: createDocAttachment,
|
||||||
@@ -99,18 +101,39 @@ export const BlockNoteContent = ({
|
|||||||
return storedEditor;
|
return storedEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO decrypt doc.content
|
||||||
|
//localStorage.getItem('KEY');
|
||||||
|
|
||||||
|
const docId = 'uuid-du-doc';
|
||||||
|
const purpose = `doc:${docId}`;
|
||||||
|
const key = e2eClient.findKeyByPurpose(purpose);
|
||||||
|
if (!key) {
|
||||||
|
alert('probleme de key');
|
||||||
|
// return;
|
||||||
|
} else {
|
||||||
|
const decryptedMessage = e2eClient.decrypt(
|
||||||
|
doc.content,
|
||||||
|
key.keychainFingerprint,
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('decryptedMessage', decryptedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
return BlockNoteEditorCore.create({
|
return BlockNoteEditorCore.create({
|
||||||
collaboration: {
|
// collaboration: {
|
||||||
provider,
|
// provider,
|
||||||
fragment: provider.document.getXmlFragment('document-store'),
|
// fragment: provider.document.getXmlFragment('document-store'),
|
||||||
user: {
|
// user: {
|
||||||
name: userData?.email || 'Anonymous',
|
// name: userData?.email || 'Anonymous',
|
||||||
color: randomColor(),
|
// color: randomColor(),
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
uploadFile,
|
uploadFile,
|
||||||
|
initialContent: JSON.parse(doc.content),
|
||||||
});
|
});
|
||||||
}, [provider, storedEditor, uploadFile, userData?.email]);
|
}, [doc.content, storedEditor, uploadFile]);
|
||||||
|
|
||||||
|
useSaveDoc(doc.id, provider.document, canSave, editor);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setStore(storeId, { editor });
|
setStore(storeId, { editor });
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { BlockNoteEditor } from '@blocknote/core';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import * as Y from 'yjs';
|
import * as Y from 'yjs';
|
||||||
@@ -6,11 +7,18 @@ import { useUpdateDoc } from '@/features/docs/doc-management/';
|
|||||||
import { KEY_LIST_DOC_VERSIONS } from '@/features/docs/doc-versioning';
|
import { KEY_LIST_DOC_VERSIONS } from '@/features/docs/doc-versioning';
|
||||||
|
|
||||||
import { toBase64 } from '../utils';
|
import { toBase64 } from '../utils';
|
||||||
|
import { useE2ESDKClient } from '@socialgouv/e2esdk-react';
|
||||||
|
|
||||||
const useSaveDoc = (docId: string, doc: Y.Doc, canSave: boolean) => {
|
const useSaveDoc = (
|
||||||
|
docId: string,
|
||||||
|
doc: Y.Doc,
|
||||||
|
canSave: boolean,
|
||||||
|
editor: BlockNoteEditor,
|
||||||
|
) => {
|
||||||
const { mutate: updateDoc } = useUpdateDoc({
|
const { mutate: updateDoc } = useUpdateDoc({
|
||||||
listInvalideQueries: [KEY_LIST_DOC_VERSIONS],
|
listInvalideQueries: [KEY_LIST_DOC_VERSIONS],
|
||||||
});
|
});
|
||||||
|
const e2eClient = useE2ESDKClient();
|
||||||
const [initialDoc, setInitialDoc] = useState<string>(
|
const [initialDoc, setInitialDoc] = useState<string>(
|
||||||
toBase64(Y.encodeStateAsUpdate(doc)),
|
toBase64(Y.encodeStateAsUpdate(doc)),
|
||||||
);
|
);
|
||||||
@@ -56,14 +64,32 @@ const useSaveDoc = (docId: string, doc: Y.Doc, canSave: boolean) => {
|
|||||||
}, [canSave, hasChanged]);
|
}, [canSave, hasChanged]);
|
||||||
|
|
||||||
const saveDoc = useCallback(() => {
|
const saveDoc = useCallback(() => {
|
||||||
const newDoc = toBase64(Y.encodeStateAsUpdate(doc));
|
const newDoc = JSON.stringify(editor.document);
|
||||||
|
//const newDoc = toBase64(Y.encodeStateAsUpdate(doc));
|
||||||
|
|
||||||
|
// TODO encode the content
|
||||||
|
|
||||||
|
const docId = 'uuid-du-doc';
|
||||||
|
const purpose = `doc:${docId}`;
|
||||||
|
const key = e2eClient.findKeyByPurpose(purpose);
|
||||||
|
if (!key) {
|
||||||
|
alert('probleme de key');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const encrypted = e2eClient.encrypt(newDoc, key.keychainFingerprint);
|
||||||
|
|
||||||
|
console.log('encrypted', encrypted);
|
||||||
|
|
||||||
|
// todo
|
||||||
|
|
||||||
setInitialDoc(newDoc);
|
setInitialDoc(newDoc);
|
||||||
|
|
||||||
updateDoc({
|
updateDoc({
|
||||||
id: docId,
|
id: docId,
|
||||||
content: newDoc,
|
content: newDoc,
|
||||||
});
|
});
|
||||||
}, [doc, docId, updateDoc]);
|
}, [docId, editor?.document, updateDoc]);
|
||||||
|
|
||||||
const timeout = useRef<NodeJS.Timeout>();
|
const timeout = useRef<NodeJS.Timeout>();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ export const useDocStore = create<UseDocStore>((set, get) => ({
|
|||||||
guid: storeId,
|
guid: storeId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (initialDoc) {
|
// if (initialDoc) {
|
||||||
Y.applyUpdate(doc, Buffer.from(initialDoc, 'base64'));
|
// Y.applyUpdate(doc, Buffer.from(initialDoc, 'base64'));
|
||||||
}
|
// }
|
||||||
|
|
||||||
const provider = new HocuspocusProvider({
|
const provider = new HocuspocusProvider({
|
||||||
url: providerUrl(storeId),
|
url: providerUrl(storeId),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user