WIP import_id #9
@ -77,6 +77,10 @@ const mimeTypesAccepted: { [key: string]: IMimeTypes } = {
|
|||||||
extension: "txt",
|
extension: "txt",
|
||||||
size: 104857600, // 100MB
|
size: 104857600, // 100MB
|
||||||
},
|
},
|
||||||
|
"application/json": {
|
||||||
|
extension: "json",
|
||||||
|
size: 104857600, // 100MB
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type IDocumentFileBase = {
|
type IDocumentFileBase = {
|
||||||
|
@ -13,7 +13,6 @@ type IProps = {
|
|||||||
|
|
||||||
export default function StepImportProfile(props: IProps) {
|
export default function StepImportProfile(props: IProps) {
|
||||||
const { onSubmit, onBack, validationErrors } = props;
|
const { onSubmit, onBack, validationErrors } = props;
|
||||||
const [importedFile, setImportedFile] = useState<File | null>(null);
|
|
||||||
const [profileData, setProfileData] = useState<any>(null);
|
const [profileData, setProfileData] = useState<any>(null);
|
||||||
const [error, setError] = useState<string>("");
|
const [error, setError] = useState<string>("");
|
||||||
|
|
||||||
@ -22,44 +21,32 @@ export default function StepImportProfile(props: IProps) {
|
|||||||
return data &&
|
return data &&
|
||||||
typeof data === "object" &&
|
typeof data === "object" &&
|
||||||
data.version &&
|
data.version &&
|
||||||
data.userData &&
|
data.user_data &&
|
||||||
typeof data.userData === "object";
|
typeof data.user_data === "object";
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFileUpload = useCallback(async (files: File[]) => {
|
const handleFileUpload = useCallback((files: File[]) => {
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
// Validate file type
|
|
||||||
if (file.type !== "application/json") {
|
|
||||||
setError("Veuillez sélectionner un fichier JSON valide.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate file size (max 1MB)
|
|
||||||
if (file.size > 1024 * 1024) {
|
|
||||||
setError("Le fichier est trop volumineux. Taille maximum : 1MB.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setImportedFile(file);
|
|
||||||
setError("");
|
setError("");
|
||||||
|
|
||||||
// Read and parse JSON
|
// Read and parse JSON
|
||||||
try {
|
file.text()
|
||||||
const text = await file.text();
|
.then((text) => {
|
||||||
const data = JSON.parse(text);
|
const data = JSON.parse(text);
|
||||||
|
|
||||||
// Validate profile structure
|
// Validate profile structure
|
||||||
if (!validateProfileStructure(data)) {
|
if (!validateProfileStructure(data)) {
|
||||||
setError("Le fichier ne contient pas un profil valide.");
|
setError('Le fichier ne contient pas un profil valide.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setProfileData(data);
|
setProfileData(data);
|
||||||
} catch (err) {
|
})
|
||||||
setError("Erreur lors de la lecture du fichier JSON.");
|
.catch((e) => {
|
||||||
}
|
setError(`Erreur lors de la lecture du fichier JSON: ${e}`);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSubmit = useCallback(() => {
|
const handleSubmit = useCallback(() => {
|
||||||
@ -100,15 +87,12 @@ export default function StepImportProfile(props: IProps) {
|
|||||||
<Typography typo={ETypo.TEXT_LG_SEMIBOLD} className={classes["preview-title"]}>
|
<Typography typo={ETypo.TEXT_LG_SEMIBOLD} className={classes["preview-title"]}>
|
||||||
Profil détecté :
|
Profil détecté :
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography typo={ETypo.TEXT_MD_REGULAR}>
|
|
||||||
{profileData.userData?.email || "Email non disponible"}
|
|
||||||
</Typography>
|
|
||||||
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_NEUTRAL_600}>
|
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_NEUTRAL_600}>
|
||||||
Version : {profileData.version}
|
Version : {profileData.version}
|
||||||
</Typography>
|
</Typography>
|
||||||
{profileData.exportedAt && (
|
{profileData.exported_at && (
|
||||||
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_NEUTRAL_600}>
|
<Typography typo={ETypo.TEXT_SM_REGULAR} color={ETypoColor.COLOR_NEUTRAL_600}>
|
||||||
Exporté le : {new Date(profileData.exportedAt).toLocaleDateString('fr-FR')}
|
Exporté le : {new Date(profileData.exported_at).toLocaleDateString('fr-FR')}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,6 +22,8 @@ import UserStore from "@Front/Stores/UserStore";
|
|||||||
import AuthModal from "src/sdk/AuthModal";
|
import AuthModal from "src/sdk/AuthModal";
|
||||||
import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService";
|
import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService";
|
||||||
import StepImportProfile from "./StepImportProfile";
|
import StepImportProfile from "./StepImportProfile";
|
||||||
|
import MessageBus from "src/sdk/MessageBus";
|
||||||
|
import Iframe from "src/sdk/Iframe";
|
||||||
|
|
||||||
export enum LoginStep {
|
export enum LoginStep {
|
||||||
EMAIL,
|
EMAIL,
|
||||||
@ -46,6 +48,7 @@ export default function Login() {
|
|||||||
const [validationErrors, setValidationErrors] = useState<ValidationError[]>([]);
|
const [validationErrors, setValidationErrors] = useState<ValidationError[]>([]);
|
||||||
const [isAuthModalOpen, setIsAuthModalOpen] = useState(false);
|
const [isAuthModalOpen, setIsAuthModalOpen] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [showIframeForImport, setShowIframeForImport] = useState(false);
|
||||||
|
|
||||||
// const openErrorModal = useCallback(() => {
|
// const openErrorModal = useCallback(() => {
|
||||||
// setIsErrorModalOpen(true);
|
// setIsErrorModalOpen(true);
|
||||||
@ -249,25 +252,21 @@ export default function Login() {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setValidationErrors([]);
|
setValidationErrors([]);
|
||||||
|
|
||||||
// Call API to validate and import profile
|
// Show iframe for import operation (but hidden from view)
|
||||||
// Note: You'll need to implement this method in your Auth service
|
setShowIframeForImport(true);
|
||||||
// const response = await Auth.getInstance().importProfile(profileData);
|
|
||||||
|
|
||||||
// For now, we'll simulate a successful import
|
// Initialize message listener for import operation
|
||||||
// In a real implementation, you would:
|
MessageBus.getInstance().initMessageListener();
|
||||||
// 1. Send the profile data to your backend
|
|
||||||
// 2. Validate the profile on the server
|
|
||||||
// 3. Return authentication tokens
|
|
||||||
// 4. Connect the user
|
|
||||||
|
|
||||||
// Simulate API call
|
// Wait for the iframe to be ready
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await MessageBus.getInstance().isReady();
|
||||||
|
|
||||||
// For demo purposes, we'll just redirect to the dashboard
|
await MessageBus.getInstance().importBackup(profileData);
|
||||||
// In reality, you'd use the response from the API
|
|
||||||
// CustomerStore.instance.connect(response.accessToken, response.refreshToken);
|
// Clean up message listener after import
|
||||||
|
MessageBus.getInstance().destroyMessageListener();
|
||||||
|
setShowIframeForImport(false);
|
||||||
|
|
||||||
// Redirect to dashboard
|
|
||||||
router.push(Module.getInstance().get().modules.pages.Folder.pages.Select.props.path);
|
router.push(Module.getInstance().get().modules.pages.Folder.pages.Select.props.path);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
setValidationErrors([
|
setValidationErrors([
|
||||||
@ -280,6 +279,7 @@ export default function Login() {
|
|||||||
]);
|
]);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
setShowIframeForImport(false);
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
@ -337,6 +337,7 @@ export default function Login() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{showIframeForImport && <Iframe showIframe={false} />}
|
||||||
{/* <Confirm
|
{/* <Confirm
|
||||||
isOpen={isErrorModalOpen}
|
isOpen={isErrorModalOpen}
|
||||||
onClose={closeErrorModal}
|
onClose={closeErrorModal}
|
||||||
|
@ -105,12 +105,7 @@ export default function LoginCallBack() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function getUser() {
|
UserStore.instance.disconnect().then(() => {
|
||||||
UserStore.instance.disconnect();
|
|
||||||
|
|
||||||
// TODO: review
|
|
||||||
// HACK: If start with http://local.lecoffreio.4nkweb:3000/authorized-client
|
|
||||||
// Replace with http://localhost:3000/authorized-client
|
|
||||||
if (window.location.href.startsWith('http://local.lecoffreio.4nkweb:3000/authorized-client')) {
|
if (window.location.href.startsWith('http://local.lecoffreio.4nkweb:3000/authorized-client')) {
|
||||||
window.location.href = window.location.href.replace('http://local.lecoffreio.4nkweb:3000/authorized-client', 'http://localhost:3000/authorized-client');
|
window.location.href = window.location.href.replace('http://local.lecoffreio.4nkweb:3000/authorized-client', 'http://localhost:3000/authorized-client');
|
||||||
return;
|
return;
|
||||||
@ -119,22 +114,11 @@ export default function LoginCallBack() {
|
|||||||
const code = router.query["code"];
|
const code = router.query["code"];
|
||||||
if (code) {
|
if (code) {
|
||||||
try {
|
try {
|
||||||
const idNotUser: any = await Auth.getInstance().getIdNotUser(code as string);
|
Auth.getInstance().getIdNotUser(code as string).then((idNotUser: any) => {
|
||||||
setIdNotUser(idNotUser);
|
setIdNotUser(idNotUser);
|
||||||
setIsAuthModalOpen(true);
|
setIsAuthModalOpen(true);
|
||||||
/*
|
return;
|
||||||
const token: any = null;
|
});
|
||||||
if (!token) return router.push(Module.getInstance().get().modules.pages.Login.props.path);
|
|
||||||
await UserStore.instance.connect(token.accessToken, token.refreshToken);
|
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
|
||||||
if (!jwt) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
|
|
||||||
if (jwt.rules && !jwt.rules.includes("GET folders")) {
|
|
||||||
return router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path);
|
|
||||||
}
|
|
||||||
setIsAuthModalOpen(true);
|
|
||||||
//return router.push(Module.getInstance().get().modules.pages.Folder.props.path);
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
if (e.http_status === 401 && e.message === "Email not found") {
|
if (e.http_status === 401 && e.message === "Email not found") {
|
||||||
return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=3");
|
return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=3");
|
||||||
@ -145,24 +129,8 @@ export default function LoginCallBack() {
|
|||||||
return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
|
return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken");
|
|
||||||
if (!refreshToken) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
|
|
||||||
const isTokenRefreshed = await JwtService.getInstance().refreshToken(refreshToken);
|
|
||||||
const jwt = JwtService.getInstance().decodeJwt();
|
|
||||||
if (!jwt) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
|
|
||||||
if (!jwt.rules.includes("GET folders")) {
|
|
||||||
return router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path);
|
|
||||||
}
|
|
||||||
if (isTokenRefreshed) {
|
|
||||||
//setIsAuthModalOpen(true);
|
|
||||||
//return router.push(Module.getInstance().get().modules.pages.Folder.props.path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=2");
|
return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=2");
|
||||||
}
|
});
|
||||||
getUser();
|
|
||||||
}, [router]);
|
}, [router]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -677,6 +677,37 @@ export default class MessageBus {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public importBackup(backupFile: any): Promise<void> {
|
||||||
|
return new Promise<void>((resolve: () => void, reject: (error: string) => void) => {
|
||||||
|
const messageId = `IMPORT_BACKUP_${uuidv4()}`;
|
||||||
|
|
||||||
|
const unsubscribe = EventBus.getInstance().on('BACKUP_IMPORTED', (responseId: string) => {
|
||||||
|
console.log('BACKUP_IMPORTED', responseId, messageId);
|
||||||
|
if (responseId !== messageId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsubscribe();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
const unsubscribeError = EventBus.getInstance().on('ERROR_BACKUP_IMPORTED', (responseId: string, error: string) => {
|
||||||
|
if (responseId !== messageId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsubscribeError();
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('IMPORT_BACKUP', backupFile);
|
||||||
|
|
||||||
|
this.sendMessage({
|
||||||
|
type: 'IMPORT_BACKUP',
|
||||||
|
backupFile: JSON.stringify(backupFile),
|
||||||
|
messageId
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public verifyMerkleProof(merkleProof: string, documentHash: string): Promise<boolean> {
|
public verifyMerkleProof(merkleProof: string, documentHash: string): Promise<boolean> {
|
||||||
return new Promise<boolean>((resolve: (isValid: boolean) => void, reject: (error: string) => void) => {
|
return new Promise<boolean>((resolve: (isValid: boolean) => void, reject: (error: string) => void) => {
|
||||||
this.checkToken().then(() => {
|
this.checkToken().then(() => {
|
||||||
@ -900,6 +931,10 @@ export default class MessageBus {
|
|||||||
this.doHandleMessage(message.messageId, 'BACKUP_RETRIEVED', message, (message: any) => message.backupFile);
|
this.doHandleMessage(message.messageId, 'BACKUP_RETRIEVED', message, (message: any) => message.backupFile);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'BACKUP_IMPORTED': // IMPORT_BACKUP
|
||||||
|
this.doHandleMessage(message.messageId, 'BACKUP_IMPORTED', message, () => { });
|
||||||
|
break;
|
||||||
|
|
||||||
case 'ERROR':
|
case 'ERROR':
|
||||||
console.error('Error:', message);
|
console.error('Error:', message);
|
||||||
this.errors[message.messageId] = message.error;
|
this.errors[message.messageId] = message.error;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user