mirror of
https://github.com/ramvignesh-b/pi-ku.git
synced 2026-05-04 08:56:52 +00:00
feat: implement encrypted metadata support and fix public_id handling in letter serialization
This commit is contained in:
@@ -30,7 +30,7 @@ class LetterSerializer(serializers.ModelSerializer):
|
|||||||
"updated_at",
|
"updated_at",
|
||||||
"images",
|
"images",
|
||||||
] # user to be fetched from request
|
] # user to be fetched from request
|
||||||
read_only_fields = ["public_id", "created_at", "updated_at"]
|
read_only_fields = ["created_at", "updated_at"]
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
if (data.get("encrypted_content") or data.get("encrypted_metadata")) and not data.get("encrypted_dek"):
|
if (data.get("encrypted_content") or data.get("encrypted_metadata")) and not data.get("encrypted_dek"):
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ class LetterView(generics.ListCreateAPIView):
|
|||||||
return Letter.objects.filter(user=self.request.user)
|
return Letter.objects.filter(user=self.request.user)
|
||||||
|
|
||||||
def put(self, request, public_id):
|
def put(self, request, public_id):
|
||||||
serializer = self.get_serializer(data=request.data)
|
data = request.data.copy()
|
||||||
|
# remove public_id from data to avoid UniqueValidator firing
|
||||||
|
# since we use it from the URL for update_or_create anyway
|
||||||
|
data.pop("public_id", None)
|
||||||
|
serializer = self.get_serializer(data=data)
|
||||||
|
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,15 @@ const PAD = 36;
|
|||||||
|
|
||||||
export type CanvasTools = {
|
export type CanvasTools = {
|
||||||
addImage: (url: string, file: File) => void;
|
addImage: (url: string, file: File) => void;
|
||||||
getData: () => { objects: any };
|
getData: () => { objects: any[] };
|
||||||
getJsonData: () => string;
|
getJsonData: () => string;
|
||||||
getImages: () => { src: string; file: File }[];
|
getImages: () => { src: string; file: File }[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface FabricImageWithFile extends fabric.FabricImage {
|
||||||
|
_customRawFile: File;
|
||||||
|
}
|
||||||
|
|
||||||
export const ComposeCanvas = forwardRef<CanvasTools>((_props, ref) => {
|
export const ComposeCanvas = forwardRef<CanvasTools>((_props, ref) => {
|
||||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
@@ -150,7 +154,7 @@ export const ComposeCanvas = forwardRef<CanvasTools>((_props, ref) => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
getData: () => {
|
getData: () => {
|
||||||
if (!fabricRef.current) return "";
|
if (!fabricRef.current) return { objects: [] };
|
||||||
return fabricRef.current.toJSON();
|
return fabricRef.current.toJSON();
|
||||||
},
|
},
|
||||||
getJsonData: () => {
|
getJsonData: () => {
|
||||||
@@ -159,8 +163,11 @@ export const ComposeCanvas = forwardRef<CanvasTools>((_props, ref) => {
|
|||||||
},
|
},
|
||||||
getImages: () => {
|
getImages: () => {
|
||||||
if (!fabricRef.current) return [];
|
if (!fabricRef.current) return [];
|
||||||
return fabricRef.current.getObjects("Image").map((img: any) => ({
|
const images = fabricRef.current.getObjects(
|
||||||
src: img._element.currentSrc,
|
"Image",
|
||||||
|
) as FabricImageWithFile[];
|
||||||
|
return images.map((img) => ({
|
||||||
|
src: (img.getElement() as HTMLImageElement).currentSrc,
|
||||||
file: img._customRawFile,
|
file: img._customRawFile,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ import { useKeyStore } from "../store/useKeyStore";
|
|||||||
import { CryptoUtils } from "../utils/crypto";
|
import { CryptoUtils } from "../utils/crypto";
|
||||||
|
|
||||||
export default function Editor() {
|
export default function Editor() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
// check for existing letter
|
||||||
const { public_id } = useParams();
|
const { public_id } = useParams();
|
||||||
const letterIdRef = useRef<string>(public_id ?? "");
|
const letterIdRef = useRef<string>(public_id ?? "");
|
||||||
const navigate = useNavigate();
|
|
||||||
const [isSealing, setIsSealing] = useState(false);
|
const [isSealing, setIsSealing] = useState(false);
|
||||||
const [isSaveSuccess, setIsSaveSuccess] = useState(false);
|
const [isSaveSuccess, setIsSaveSuccess] = useState(false);
|
||||||
|
|
||||||
@@ -40,9 +42,11 @@ export default function Editor() {
|
|||||||
|
|
||||||
async function handleSeal(): Promise<void> {
|
async function handleSeal(): Promise<void> {
|
||||||
if (!public_id) {
|
if (!public_id) {
|
||||||
|
// if no uuid slug, then generate a new one and update params
|
||||||
letterIdRef.current = crypto.randomUUID();
|
letterIdRef.current = crypto.randomUUID();
|
||||||
navigate(ROUTES.WRITE(letterIdRef.current), { replace: true });
|
navigate(ROUTES.WRITE(letterIdRef.current), { replace: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSealing) return;
|
if (isSealing) return;
|
||||||
setIsSealing(true);
|
setIsSealing(true);
|
||||||
const cryptoUtils = new CryptoUtils();
|
const cryptoUtils = new CryptoUtils();
|
||||||
@@ -79,7 +83,11 @@ export default function Editor() {
|
|||||||
JSON.stringify(canvasData),
|
JSON.stringify(canvasData),
|
||||||
masterKey,
|
masterKey,
|
||||||
);
|
);
|
||||||
const encrypted_metadata = "";
|
|
||||||
|
const encrypted_metadata = await cryptoUtils.encryptMetadata(
|
||||||
|
{ recipient },
|
||||||
|
masterKey,
|
||||||
|
);
|
||||||
|
|
||||||
// upload to server
|
// upload to server
|
||||||
/*
|
/*
|
||||||
@@ -98,7 +106,7 @@ export default function Editor() {
|
|||||||
formData.append("status", "SEALED");
|
formData.append("status", "SEALED");
|
||||||
formData.append("encrypted_content", encrypted_letter.encrypted_content);
|
formData.append("encrypted_content", encrypted_letter.encrypted_content);
|
||||||
formData.append("encrypted_dek", encrypted_letter.encrypted_dek);
|
formData.append("encrypted_dek", encrypted_letter.encrypted_dek);
|
||||||
formData.append("encrypted_metadata", encrypted_metadata);
|
formData.append("encrypted_metadata", encrypted_metadata.encrypted_content);
|
||||||
encImageFilesMap.forEach((image, filename) => {
|
encImageFilesMap.forEach((image, filename) => {
|
||||||
formData.append("image_files", image, filename);
|
formData.append("image_files", image, filename);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user