diff --git a/.github/workflows/backend-build.yml b/.github/workflows/backend-build.yml new file mode 100644 index 00000000..c0682d10 --- /dev/null +++ b/.github/workflows/backend-build.yml @@ -0,0 +1,114 @@ +name: Backend - Build & Lint + +on: + push: + branches: [main] + paths: + - "backend/**/**" + pull_request: + branches: [main] + paths: + - "backend/**/**" + +jobs: + lint: + name: Static Analysis (golangci-lint) + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.24.4" + cache-dependency-path: backend/gestion/go.sum + + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + continue-on-error: true + with: + version: latest + working-directory: backend/gestion + args: --timeout=5m + + build: + name: Build + needs: lint + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.24.4" + cache-dependency-path: backend/gestion/go.sum + + - name: Download dependencies + working-directory: backend/gestion + run: go mod download + + - name: Build + working-directory: backend/gestion + run: go build -v ./... + + - name: Upload binary + uses: actions/upload-artifact@v4 + with: + name: backend-binary + path: backend/gestion/gestion + retention-days: 7 + + docker: + name: Docker Build & Push + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + + steps: + - uses: actions/checkout@v4 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build & push backend (runtime) + uses: docker/build-push-action@v6 + with: + context: . + file: docker/backend/Dockerfile + target: runtime + push: true + tags: xor1234/backend-mln:latest + + - name: Build & push WAF + uses: docker/build-push-action@v6 + with: + context: . + file: docker/backend/Dockerfile + target: waf + push: true + tags: xor1234/backend-mln:waf + + deploy: + name: SSH Deploy + needs: docker + runs-on: ubuntu-latest + + steps: + - name: SSH deploy + uses: appleboy/ssh-action@v1 + with: + host: ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && secrets.SERVER_HOST_PROD || secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USER }} + key: ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && secrets.SERVER_SSH_KEY_PROD || secrets.SERVER_SSH_KEY }} + script: | + docker compose -f ${{ secrets.COMPOSE_PATH }} pull backend waf + docker compose -f ${{ secrets.COMPOSE_PATH }} up -d --no-deps backend waf diff --git a/.github/workflows/frontend-admin-build.yml b/.github/workflows/frontend-admin-build.yml new file mode 100644 index 00000000..498c1a3a --- /dev/null +++ b/.github/workflows/frontend-admin-build.yml @@ -0,0 +1,82 @@ +name: Frontend Admin - EAS Build + +on: + push: + branches: [main, pre-prod] + paths: + - "frontend-admin/**" + pull_request: + branches: [main, pre-prod] + paths: + - "frontend-admin/**" + +jobs: + typecheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: frontend-admin/package-lock.json + + - name: Install dependencies + working-directory: frontend-admin + run: npm ci + + - name: Typecheck + working-directory: frontend-admin + run: npx tsc --noEmit + + build-apk: + needs: typecheck + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: frontend-admin/package-lock.json + + - name: Setup Expo & EAS CLI + uses: expo/expo-github-action@v8 + with: + eas-version: latest + token: ${{ secrets.EXPO_TOKEN }} + + - name: Install dependencies + working-directory: frontend-admin + run: npm ci + + - name: Inject EAS project ID + working-directory: frontend-admin + run: | + jq '.expo.extra.eas.projectId = "${{ secrets.EXPO_PROJECT_ID }}"' app.json > app.tmp.json + mv app.tmp.json app.json + + - name: Build APK + working-directory: frontend-admin + env: + EAS_BUILD_NO_EXPO_GO_WARNING: true + run: eas build --platform android ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && '--profile production' || '--profile preview' }} --non-interactive + + - name: Download APK + working-directory: frontend-admin + run: | + APK_URL=$(eas build:list --platform android --status finished --limit 1 --json --non-interactive | jq -r '.[0].artifacts.buildUrl') + curl -L -o admin-panel-prod.apk "$APK_URL" + + - name: Upload production APK artifact + uses: actions/upload-artifact@v4 + with: + name: admin-panel-android-prod-apk + path: frontend-admin/admin-panel-prod.apk + retention-days: 14 diff --git a/.github/workflows/frontend-client-build.yml b/.github/workflows/frontend-client-build.yml new file mode 100644 index 00000000..3bdeed9d --- /dev/null +++ b/.github/workflows/frontend-client-build.yml @@ -0,0 +1,86 @@ +name: Frontend Client - EAS Build + +on: + push: + branches: [main, pre-prod] + paths: + - "mobile/**" + pull_request: + branches: [main, pre-prod] + paths: + - "mobile/**" + +jobs: + typecheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: mobile/package-lock.json + + - name: Install dependencies + working-directory: mobile + run: npm ci + + - name: Typecheck + working-directory: mobile + run: npx tsc --noEmit + + build-apk: + needs: typecheck + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: mobile/package-lock.json + + - name: Setup Expo & EAS CLI + uses: expo/expo-github-action@v8 + with: + eas-version: latest + token: ${{ secrets.EXPO_TOKEN }} + + - name: Install dependencies + working-directory: mobile + run: npm ci + + - name: Inject EAS project ID + working-directory: mobile + run: | + jq '.expo.extra.eas.projectId = "${{ secrets.EXPO_PROJECT_ID_CLIENT }}"' app.json > app.tmp.json + mv app.tmp.json app.json + + - name: Debug app.json + working-directory: mobile + run: cat app.json + + - name: Build APK + working-directory: mobile + env: + EAS_BUILD_NO_EXPO_GO_WARNING: true + run: eas build --platform android ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && '--profile production' || '--profile preview' }} --non-interactive + + - name: Download production APK + working-directory: mobile + run: | + APK_URL=$(eas build:list --platform android --status finished --limit 1 --json --non-interactive | jq -r '.[0].artifacts.buildUrl') + curl -L -o client-panel-prod.apk "$APK_URL" + + - name: Upload production APK artifact + uses: actions/upload-artifact@v4 + with: + name: client-panel-android-prod-apk + path: mobile/client-panel-prod.apk + retention-days: 14 diff --git a/.github/workflows/frontend-web-build.yml b/.github/workflows/frontend-web-build.yml new file mode 100644 index 00000000..5538fef5 --- /dev/null +++ b/.github/workflows/frontend-web-build.yml @@ -0,0 +1,111 @@ +name: Frontend Web - Build & Lint + +on: + push: + branches: [main, pre-prod] + paths: + - "frontend-prep/**" + - "docker/frontend/**" + pull_request: + branches: [main, pre-prod] + paths: + - "frontend-prep/**" + - "docker/frontend/**" + +jobs: + lint-typecheck: + name: Lint & Typecheck + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: frontend-prep/package-lock.json + + - name: Install dependencies + working-directory: frontend-prep + run: npm ci + + - name: Typecheck + working-directory: frontend-prep + run: npx tsc -b --noEmit + + - name: Lint + working-directory: frontend-prep + run: npm run lint + + build: + name: Build + needs: lint-typecheck + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: frontend-prep/package-lock.json + + - name: Install dependencies + working-directory: frontend-prep + run: npm ci + + - name: Build + working-directory: frontend-prep + env: + VITE_TOMTOM_API_KEY: ${{ secrets.VITE_TOMTOM_API_KEY }} + run: npm run build + + docker: + name: Docker Build & Push + needs: build + runs-on: ubuntu-latest + if: > + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/pre-prod')) || + (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'pre-prod')) + + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build & push frontend + uses: docker/build-push-action@v6 + with: + context: . + file: docker/frontend/Dockerfile + push: true + tags: xor1234/frontend-mln:${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && 'latest' || 'pre-prod' }} + build-args: | + VITE_TOMTOM_API_KEY=${{ secrets.VITE_TOMTOM_API_KEY }} + + deploy: + name: Deploy to server + needs: docker + runs-on: ubuntu-latest + + steps: + - name: SSH deploy + uses: appleboy/ssh-action@v1 + with: + host: ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && secrets.SERVER_HOST_PROD || secrets.SERVER_HOST }} + username: ${{ secrets.SERVER_USER }} + key: ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && secrets.SERVER_SSH_KEY_PROD || secrets.SERVER_SSH_KEY }} + script: | + docker compose -f ${{ secrets.COMPOSE_PATH }} pull frontend + docker compose -f ${{ secrets.COMPOSE_PATH }} up -d --no-deps frontend diff --git a/backend/gestion/handlers/auth.go b/backend/gestion/handlers/auth.go index 6b351778..5ca09350 100644 --- a/backend/gestion/handlers/auth.go +++ b/backend/gestion/handlers/auth.go @@ -409,9 +409,9 @@ func GetClient2FAStatus(c *gin.Context) { settings, _ := database.GetSettings() c.JSON(http.StatusOK, gin.H{ - "two_fa_enabled": client.TwoFAEnabled, - "telegram_linked": tgLinked, - "admin_2fa_enabled": settings.Telegram2FAEnabled, + "two_fa_enabled": client.TwoFAEnabled, + "telegram_linked": tgLinked, + "admin_2fa_enabled": settings.Telegram2FAEnabled, }) } @@ -454,7 +454,6 @@ func ToggleClient2FA(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"success": true, "two_fa_enabled": req.Enabled}) } -// ChangePassword permet à un client de changer son mot de passe func ChangePassword(c *gin.Context) { var req struct { CurrentPassword string `json:"current_password" binding:"required"`