Ajout protection mot de passe et installeur Windows complet
- Mot de passe SHA-256 au lancement (3 tentatives, saisie masquee) - install.bat : installeur/desinstalleur/mise a jour tout-en-un - Telecharge et installe Git portable si absent - Telecharge et installe Python 3.12 embarque si absent - Installe pip et les dependances automatiquement - Clone le depot Gitea - Cree raccourcis Bureau et Menu Demarrer - Mise a jour en 1 clic (git pull + pip upgrade) - Desinstallation complete avec confirmation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
361
install.bat
Normal file
361
install.bat
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
@echo off
|
||||||
|
chcp 65001 >nul 2>&1
|
||||||
|
setlocal EnableDelayedExpansion
|
||||||
|
title Copydev Imposing Tool — Installation
|
||||||
|
|
||||||
|
set "APP_NAME=Copydev Imposing Tool"
|
||||||
|
set "INSTALL_DIR=%LOCALAPPDATA%\CopydevImposingTool"
|
||||||
|
set "PYTHON_DIR=%INSTALL_DIR%\python"
|
||||||
|
set "APP_DIR=%INSTALL_DIR%\app"
|
||||||
|
set "SHORTCUT_NAME=Copydev Imposing Tool"
|
||||||
|
set "GITEA_REPO=https://git.copydev.fr/jules/copydev-imposing-tool.git"
|
||||||
|
set "PYTHON_VERSION=3.12.8"
|
||||||
|
set "PYTHON_URL=https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-embed-amd64.zip"
|
||||||
|
set "GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py"
|
||||||
|
set "GIT_URL=https://github.com/git-for-windows/git/releases/download/v2.47.1.windows.2/MinGit-2.47.1.2-64-bit.zip"
|
||||||
|
|
||||||
|
:: ============================================================
|
||||||
|
:: MENU PRINCIPAL
|
||||||
|
:: ============================================================
|
||||||
|
:MENU
|
||||||
|
cls
|
||||||
|
echo ============================================================
|
||||||
|
echo %APP_NAME%
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
echo 1. Installer
|
||||||
|
echo 2. Mettre a jour
|
||||||
|
echo 3. Desinstaller
|
||||||
|
echo 4. Quitter
|
||||||
|
echo.
|
||||||
|
set /p "CHOIX=Votre choix [1-4] : "
|
||||||
|
|
||||||
|
if "%CHOIX%"=="1" goto INSTALL
|
||||||
|
if "%CHOIX%"=="2" goto UPDATE
|
||||||
|
if "%CHOIX%"=="3" goto UNINSTALL
|
||||||
|
if "%CHOIX%"=="4" goto END
|
||||||
|
echo Choix invalide.
|
||||||
|
timeout /t 2 >nul
|
||||||
|
goto MENU
|
||||||
|
|
||||||
|
:: ============================================================
|
||||||
|
:: INSTALLATION
|
||||||
|
:: ============================================================
|
||||||
|
:INSTALL
|
||||||
|
cls
|
||||||
|
echo ============================================================
|
||||||
|
echo INSTALLATION de %APP_NAME%
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
:: Verifier si deja installe
|
||||||
|
if exist "%INSTALL_DIR%\app\main.py" (
|
||||||
|
echo [!] L'application est deja installee dans :
|
||||||
|
echo %INSTALL_DIR%
|
||||||
|
echo.
|
||||||
|
set /p "REINSTALL=Voulez-vous reinstaller ? [O/N] : "
|
||||||
|
if /i "!REINSTALL!" neq "O" goto MENU
|
||||||
|
echo.
|
||||||
|
echo Suppression de l'ancienne installation...
|
||||||
|
rmdir /s /q "%APP_DIR%" 2>nul
|
||||||
|
)
|
||||||
|
|
||||||
|
:: Creer le repertoire d'installation
|
||||||
|
echo [1/7] Creation du repertoire d'installation...
|
||||||
|
if not exist "%INSTALL_DIR%" mkdir "%INSTALL_DIR%"
|
||||||
|
if not exist "%INSTALL_DIR%\temp" mkdir "%INSTALL_DIR%\temp"
|
||||||
|
|
||||||
|
:: ---- GIT ----
|
||||||
|
:INSTALL_GIT
|
||||||
|
echo [2/7] Verification de Git...
|
||||||
|
where git >nul 2>&1
|
||||||
|
if %ERRORLEVEL%==0 (
|
||||||
|
echo Git est deja installe.
|
||||||
|
set "GIT_CMD=git"
|
||||||
|
goto INSTALL_PYTHON
|
||||||
|
)
|
||||||
|
|
||||||
|
:: Git portable
|
||||||
|
if exist "%INSTALL_DIR%\git\cmd\git.exe" (
|
||||||
|
echo Git portable detecte.
|
||||||
|
set "GIT_CMD=%INSTALL_DIR%\git\cmd\git.exe"
|
||||||
|
goto INSTALL_PYTHON
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Telechargement de Git portable...
|
||||||
|
if not exist "%INSTALL_DIR%\git" mkdir "%INSTALL_DIR%\git"
|
||||||
|
powershell -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%GIT_URL%' -OutFile '%INSTALL_DIR%\temp\git.zip' }" 2>nul
|
||||||
|
if not exist "%INSTALL_DIR%\temp\git.zip" (
|
||||||
|
echo [ERREUR] Impossible de telecharger Git.
|
||||||
|
echo Verifiez votre connexion internet.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
echo Extraction de Git...
|
||||||
|
powershell -Command "Expand-Archive -Force '%INSTALL_DIR%\temp\git.zip' '%INSTALL_DIR%\git'" 2>nul
|
||||||
|
del "%INSTALL_DIR%\temp\git.zip" 2>nul
|
||||||
|
set "GIT_CMD=%INSTALL_DIR%\git\cmd\git.exe"
|
||||||
|
echo Git portable installe.
|
||||||
|
|
||||||
|
:: ---- PYTHON ----
|
||||||
|
:INSTALL_PYTHON
|
||||||
|
echo [3/7] Verification de Python...
|
||||||
|
|
||||||
|
:: Verifier Python systeme
|
||||||
|
where python >nul 2>&1
|
||||||
|
if %ERRORLEVEL%==0 (
|
||||||
|
for /f "tokens=*" %%i in ('python --version 2^>^&1') do set "PY_VER=%%i"
|
||||||
|
echo !PY_VER! detecte.
|
||||||
|
set "PYTHON_CMD=python"
|
||||||
|
goto INSTALL_PIP
|
||||||
|
)
|
||||||
|
|
||||||
|
:: Python embarque
|
||||||
|
if exist "%PYTHON_DIR%\python.exe" (
|
||||||
|
echo Python embarque detecte.
|
||||||
|
set "PYTHON_CMD=%PYTHON_DIR%\python.exe"
|
||||||
|
goto INSTALL_PIP
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Telechargement de Python %PYTHON_VERSION% embarque...
|
||||||
|
if not exist "%PYTHON_DIR%" mkdir "%PYTHON_DIR%"
|
||||||
|
powershell -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%PYTHON_URL%' -OutFile '%INSTALL_DIR%\temp\python.zip' }" 2>nul
|
||||||
|
if not exist "%INSTALL_DIR%\temp\python.zip" (
|
||||||
|
echo [ERREUR] Impossible de telecharger Python.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
echo Extraction de Python...
|
||||||
|
powershell -Command "Expand-Archive -Force '%INSTALL_DIR%\temp\python.zip' '%PYTHON_DIR%'" 2>nul
|
||||||
|
del "%INSTALL_DIR%\temp\python.zip" 2>nul
|
||||||
|
|
||||||
|
:: Activer pip dans Python embarque (decommenter import site)
|
||||||
|
for %%f in ("%PYTHON_DIR%\python*._pth") do (
|
||||||
|
powershell -Command "(Get-Content '%%f') -replace '#import site','import site' | Set-Content '%%f'"
|
||||||
|
)
|
||||||
|
set "PYTHON_CMD=%PYTHON_DIR%\python.exe"
|
||||||
|
echo Python %PYTHON_VERSION% embarque installe.
|
||||||
|
|
||||||
|
:: ---- PIP ----
|
||||||
|
:INSTALL_PIP
|
||||||
|
echo [4/7] Verification de pip...
|
||||||
|
"%PYTHON_CMD%" -m pip --version >nul 2>&1
|
||||||
|
if %ERRORLEVEL%==0 (
|
||||||
|
echo pip est deja installe.
|
||||||
|
goto INSTALL_DEPS
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Installation de pip...
|
||||||
|
powershell -Command "& { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%GET_PIP_URL%' -OutFile '%INSTALL_DIR%\temp\get-pip.py' }" 2>nul
|
||||||
|
"%PYTHON_CMD%" "%INSTALL_DIR%\temp\get-pip.py" --no-warn-script-location >nul 2>&1
|
||||||
|
del "%INSTALL_DIR%\temp\get-pip.py" 2>nul
|
||||||
|
echo pip installe.
|
||||||
|
|
||||||
|
:: ---- DEPENDANCES ----
|
||||||
|
:INSTALL_DEPS
|
||||||
|
echo [5/7] Installation des dependances Python...
|
||||||
|
"%PYTHON_CMD%" -m pip install --upgrade --no-warn-script-location PyQt6 pypdf reportlab pypdfium2 2>&1 | findstr /i "Successfully already"
|
||||||
|
echo Dependances installees.
|
||||||
|
|
||||||
|
:: ---- CODE SOURCE ----
|
||||||
|
:INSTALL_CODE
|
||||||
|
echo [6/7] Telechargement du code source...
|
||||||
|
if exist "%APP_DIR%\.git" (
|
||||||
|
echo Mise a jour du code existant...
|
||||||
|
pushd "%APP_DIR%"
|
||||||
|
"%GIT_CMD%" pull origin master 2>&1
|
||||||
|
popd
|
||||||
|
) else (
|
||||||
|
if exist "%APP_DIR%" rmdir /s /q "%APP_DIR%"
|
||||||
|
"%GIT_CMD%" clone "%GITEA_REPO%" "%APP_DIR%" 2>&1
|
||||||
|
)
|
||||||
|
if not exist "%APP_DIR%\main.py" (
|
||||||
|
echo [ERREUR] Le telechargement du code a echoue.
|
||||||
|
echo Verifiez l'acces a %GITEA_REPO%
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
echo Code source telecharge.
|
||||||
|
|
||||||
|
:: ---- RACCOURCIS ----
|
||||||
|
:INSTALL_SHORTCUTS
|
||||||
|
echo [7/7] Creation des raccourcis...
|
||||||
|
|
||||||
|
:: Creer le lanceur .bat
|
||||||
|
(
|
||||||
|
echo @echo off
|
||||||
|
echo cd /d "%APP_DIR%"
|
||||||
|
echo "%PYTHON_CMD%" main.py
|
||||||
|
) > "%INSTALL_DIR%\lancer.bat"
|
||||||
|
|
||||||
|
:: Creer le lanceur .vbs (sans fenetre console)
|
||||||
|
(
|
||||||
|
echo Set WshShell = CreateObject^("WScript.Shell"^)
|
||||||
|
echo WshShell.CurrentDirectory = "%APP_DIR%"
|
||||||
|
echo WshShell.Run """%PYTHON_CMD%"" ""%APP_DIR%\main.py""", 0, False
|
||||||
|
) > "%INSTALL_DIR%\lancer.vbs"
|
||||||
|
|
||||||
|
:: Raccourci Bureau
|
||||||
|
powershell -Command "& { $WshShell = New-Object -ComObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut([Environment]::GetFolderPath('Desktop') + '\%SHORTCUT_NAME%.lnk'); $Shortcut.TargetPath = '%INSTALL_DIR%\lancer.vbs'; $Shortcut.WorkingDirectory = '%APP_DIR%'; $Shortcut.Description = '%APP_NAME%'; $Shortcut.Save() }" 2>nul
|
||||||
|
echo Raccourci Bureau cree.
|
||||||
|
|
||||||
|
:: Raccourci Menu Demarrer
|
||||||
|
set "START_MENU=%APPDATA%\Microsoft\Windows\Start Menu\Programs"
|
||||||
|
powershell -Command "& { $WshShell = New-Object -ComObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut('%START_MENU%\%SHORTCUT_NAME%.lnk'); $Shortcut.TargetPath = '%INSTALL_DIR%\lancer.vbs'; $Shortcut.WorkingDirectory = '%APP_DIR%'; $Shortcut.Description = '%APP_NAME%'; $Shortcut.Save() }" 2>nul
|
||||||
|
echo Raccourci Menu Demarrer cree.
|
||||||
|
|
||||||
|
:: Nettoyer temp
|
||||||
|
rmdir /s /q "%INSTALL_DIR%\temp" 2>nul
|
||||||
|
|
||||||
|
:: ---- FIN INSTALLATION ----
|
||||||
|
echo.
|
||||||
|
echo ============================================================
|
||||||
|
echo INSTALLATION TERMINEE
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
echo Dossier : %INSTALL_DIR%
|
||||||
|
echo Lanceur : Double-cliquez sur le raccourci Bureau
|
||||||
|
echo "%SHORTCUT_NAME%"
|
||||||
|
echo.
|
||||||
|
echo Mot de passe requis au lancement.
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
|
||||||
|
:: ============================================================
|
||||||
|
:: MISE A JOUR
|
||||||
|
:: ============================================================
|
||||||
|
:UPDATE
|
||||||
|
cls
|
||||||
|
echo ============================================================
|
||||||
|
echo MISE A JOUR de %APP_NAME%
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
if not exist "%APP_DIR%\main.py" (
|
||||||
|
echo [!] L'application n'est pas installee.
|
||||||
|
echo Lancez d'abord l'installation.
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
|
||||||
|
:: Determiner Git
|
||||||
|
where git >nul 2>&1
|
||||||
|
if %ERRORLEVEL%==0 (
|
||||||
|
set "GIT_CMD=git"
|
||||||
|
) else if exist "%INSTALL_DIR%\git\cmd\git.exe" (
|
||||||
|
set "GIT_CMD=%INSTALL_DIR%\git\cmd\git.exe"
|
||||||
|
) else (
|
||||||
|
echo [ERREUR] Git introuvable. Reinstallez l'application.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
|
||||||
|
:: Determiner Python
|
||||||
|
where python >nul 2>&1
|
||||||
|
if %ERRORLEVEL%==0 (
|
||||||
|
set "PYTHON_CMD=python"
|
||||||
|
) else if exist "%PYTHON_DIR%\python.exe" (
|
||||||
|
set "PYTHON_CMD=%PYTHON_DIR%\python.exe"
|
||||||
|
) else (
|
||||||
|
echo [ERREUR] Python introuvable. Reinstallez l'application.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [1/3] Mise a jour du code source...
|
||||||
|
pushd "%APP_DIR%"
|
||||||
|
"%GIT_CMD%" fetch origin 2>&1
|
||||||
|
|
||||||
|
:: Afficher les changements
|
||||||
|
for /f %%i in ('"%GIT_CMD%" rev-list HEAD..origin/master --count 2^>nul') do set "COMMITS=%%i"
|
||||||
|
if "!COMMITS!"=="0" (
|
||||||
|
echo Deja a jour !
|
||||||
|
popd
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
echo !COMMITS! nouveau(x) commit(s) disponible(s).
|
||||||
|
"%GIT_CMD%" log --oneline HEAD..origin/master 2>nul
|
||||||
|
echo.
|
||||||
|
|
||||||
|
"%GIT_CMD%" pull origin master 2>&1
|
||||||
|
popd
|
||||||
|
echo Code mis a jour.
|
||||||
|
|
||||||
|
echo [2/3] Mise a jour des dependances...
|
||||||
|
"%PYTHON_CMD%" -m pip install --upgrade --no-warn-script-location PyQt6 pypdf reportlab pypdfium2 2>&1 | findstr /i "Successfully already"
|
||||||
|
|
||||||
|
echo [3/3] Termine !
|
||||||
|
echo.
|
||||||
|
echo ============================================================
|
||||||
|
echo MISE A JOUR TERMINEE
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
|
||||||
|
:: ============================================================
|
||||||
|
:: DESINSTALLATION
|
||||||
|
:: ============================================================
|
||||||
|
:UNINSTALL
|
||||||
|
cls
|
||||||
|
echo ============================================================
|
||||||
|
echo DESINSTALLATION de %APP_NAME%
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
if not exist "%INSTALL_DIR%" (
|
||||||
|
echo [!] L'application n'est pas installee.
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Les elements suivants seront supprimes :
|
||||||
|
echo.
|
||||||
|
echo - Dossier : %INSTALL_DIR%
|
||||||
|
echo (code, Python embarque, Git portable)
|
||||||
|
echo - Raccourci Bureau
|
||||||
|
echo - Raccourci Menu Demarrer
|
||||||
|
echo.
|
||||||
|
set /p "CONFIRM=Confirmer la desinstallation ? [O/N] : "
|
||||||
|
if /i "%CONFIRM%" neq "O" goto MENU
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo [1/3] Suppression des raccourcis...
|
||||||
|
del "%USERPROFILE%\Desktop\%SHORTCUT_NAME%.lnk" 2>nul
|
||||||
|
del "%APPDATA%\Microsoft\Windows\Start Menu\Programs\%SHORTCUT_NAME%.lnk" 2>nul
|
||||||
|
echo Raccourcis supprimes.
|
||||||
|
|
||||||
|
echo [2/3] Suppression des fichiers...
|
||||||
|
:: Tuer les processus Python potentiellement en cours
|
||||||
|
taskkill /f /im python.exe 2>nul
|
||||||
|
taskkill /f /im pythonw.exe 2>nul
|
||||||
|
timeout /t 2 >nul
|
||||||
|
|
||||||
|
rmdir /s /q "%INSTALL_DIR%" 2>nul
|
||||||
|
if exist "%INSTALL_DIR%" (
|
||||||
|
echo [!] Certains fichiers n'ont pas pu etre supprimes.
|
||||||
|
echo Supprimez manuellement : %INSTALL_DIR%
|
||||||
|
) else (
|
||||||
|
echo Fichiers supprimes.
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [3/3] Desinstallation terminee.
|
||||||
|
echo.
|
||||||
|
echo ============================================================
|
||||||
|
echo DESINSTALLATION TERMINEE
|
||||||
|
echo ============================================================
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
goto MENU
|
||||||
|
|
||||||
|
:: ============================================================
|
||||||
|
:END
|
||||||
|
echo.
|
||||||
|
echo Au revoir !
|
||||||
|
timeout /t 2 >nul
|
||||||
|
exit /b 0
|
||||||
34
main.py
34
main.py
@@ -3,12 +3,38 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import hashlib
|
||||||
|
|
||||||
# Ajouter le repertoire racine au path
|
# Ajouter le repertoire racine au path
|
||||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
from PyQt6.QtWidgets import QApplication
|
from PyQt6.QtWidgets import QApplication, QInputDialog, QMessageBox, QLineEdit
|
||||||
from app.main_window import MainWindow
|
|
||||||
|
# Hash SHA-256 du mot de passe — jamais en clair dans le code
|
||||||
|
_PASSWORD_HASH = "f3dd6962a99a2fe2e03cd8e5cfa7dafb12570bdcca1b6590e27d95dcccdf1f58"
|
||||||
|
|
||||||
|
def _hash_password(pwd):
|
||||||
|
return hashlib.sha256(pwd.encode("utf-8")).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def _check_auth():
|
||||||
|
"""Demander le mot de passe au lancement."""
|
||||||
|
max_attempts = 3
|
||||||
|
for attempt in range(max_attempts):
|
||||||
|
pwd, ok = QInputDialog.getText(
|
||||||
|
None,
|
||||||
|
"Copydev Imposing Tool",
|
||||||
|
f"Mot de passe requis ({max_attempts - attempt} essai(s) restant(s)) :",
|
||||||
|
QLineEdit.EchoMode.Password,
|
||||||
|
)
|
||||||
|
if not ok:
|
||||||
|
return False
|
||||||
|
if _hash_password(pwd) == _PASSWORD_HASH:
|
||||||
|
return True
|
||||||
|
if attempt < max_attempts - 1:
|
||||||
|
QMessageBox.warning(None, "Erreur", "Mot de passe incorrect.")
|
||||||
|
QMessageBox.critical(None, "Acces refuse", "Trop de tentatives. L'application va se fermer.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -16,6 +42,10 @@ def main():
|
|||||||
app.setApplicationName("Copydev Imposing Tool")
|
app.setApplicationName("Copydev Imposing Tool")
|
||||||
app.setOrganizationName("Copydev")
|
app.setOrganizationName("Copydev")
|
||||||
|
|
||||||
|
if not _check_auth():
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
from app.main_window import MainWindow
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
window.show()
|
window.show()
|
||||||
sys.exit(app.exec())
|
sys.exit(app.exec())
|
||||||
|
|||||||
Reference in New Issue
Block a user