From c7472d833a577cb40bace116bc44739efcc8f79a Mon Sep 17 00:00:00 2001 From: leon-morival Date: Tue, 4 Nov 2025 10:56:30 +0100 Subject: [PATCH] fix --- .gitignore | 2 +- functions/.env.example | 6 -- functions/index.js | 2 - functions/package-lock.json | 12 ---- functions/package.json | 1 - functions/src/youtube.js | 73 +++++++++++++++++++----- src/screens/Publishing/PublishYoutube.js | 2 +- youtube.md | 24 -------- 8 files changed, 60 insertions(+), 62 deletions(-) delete mode 100644 functions/.env.example delete mode 100644 youtube.md diff --git a/.gitignore b/.gitignore index f44dbbc..28a397d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ npm-debug.* web-build/ ios/ android/ - +youtube.md # macOS .DS_Store diff --git a/functions/.env.example b/functions/.env.example deleted file mode 100644 index 053cb95..0000000 --- a/functions/.env.example +++ /dev/null @@ -1,6 +0,0 @@ -YOUTUBE_CLIENT_ID=your-youtube-client-id -YOUTUBE_CLIENT_SECRET=your-youtube-client-secret -YOUTUBE_REFRESH_TOKEN=your-youtube-refresh-token -# YOUTUBE_REDIRECT_URI=http://localhost:8081 -# YOUTUBE_PRIVACY_STATUS=unlisted -# YOUTUBE_CATEGORY_ID=10 diff --git a/functions/index.js b/functions/index.js index 66bd872..6c150ce 100644 --- a/functions/index.js +++ b/functions/index.js @@ -1,5 +1,3 @@ -require("dotenv").config(); - const admin = require("firebase-admin"); // Use default credentials/environment provided by Cloud Functions. diff --git a/functions/package-lock.json b/functions/package-lock.json index 8e4d24e..fb99117 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -11,7 +11,6 @@ "@google-cloud/firestore": "^7.11.6", "@google-cloud/storage": "^7.17.1", "axios": "^1.11.0", - "dotenv": "^17.2.3", "expo-server-sdk": "^4.0.0", "ffmpeg-static": "^5.2.0", "firebase-admin": "^12.6.0", @@ -3785,17 +3784,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dotenv": { - "version": "17.2.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", - "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, "node_modules/dotprompt": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/dotprompt/-/dotprompt-1.1.2.tgz", diff --git a/functions/package.json b/functions/package.json index 668ca76..91a6097 100644 --- a/functions/package.json +++ b/functions/package.json @@ -19,7 +19,6 @@ "@google-cloud/firestore": "^7.11.6", "@google-cloud/storage": "^7.17.1", "axios": "^1.11.0", - "dotenv": "^17.2.3", "expo-server-sdk": "^4.0.0", "ffmpeg-static": "^5.2.0", "firebase-admin": "^12.6.0", diff --git a/functions/src/youtube.js b/functions/src/youtube.js index e149a20..19519e2 100644 --- a/functions/src/youtube.js +++ b/functions/src/youtube.js @@ -1,6 +1,7 @@ const { onCall, HttpsError } = require("firebase-functions/v2/https"); -const functions = require("firebase-functions"); +const { defineSecret } = require("firebase-functions/params"); const logger = require("firebase-functions/logger"); +const functions = require("firebase-functions"); const admin = require("firebase-admin"); const axios = require("axios"); const fs = require("node:fs"); @@ -9,6 +10,15 @@ const os = require("node:os"); const path = require("node:path"); const { google } = require("googleapis"); +// ---- Secrets déclarés (gen2 + Secret Manager) +const S_YT_CLIENT_ID = defineSecret("YOUTUBE_CLIENT_ID"); +const S_YT_CLIENT_SECRET = defineSecret("YOUTUBE_CLIENT_SECRET"); +const S_YT_REFRESH_TOKEN = defineSecret("YOUTUBE_REFRESH_TOKEN"); +const S_YT_REDIRECT_URI = defineSecret("YOUTUBE_REDIRECT_URI"); +const S_YT_PRIVACY_STATUS = defineSecret("YOUTUBE_PRIVACY_STATUS"); +const S_YT_CATEGORY_ID = defineSecret("YOUTUBE_CATEGORY_ID"); + +// Firestore const firestore = admin.firestore(); const projectsRef = firestore.collection("projects"); @@ -19,22 +29,47 @@ const YOUTUBE_IN_PROGRESS_STATUSES = [ "QUEUED", ]; -const getEnvYoutubeConfig = () => +// Lecture des secrets (recommandé en v2) +const getSecretsYoutubeConfig = () => Object.fromEntries( Object.entries({ - client_id: process.env.YOUTUBE_CLIENT_ID, - client_secret: process.env.YOUTUBE_CLIENT_SECRET, - refresh_token: process.env.YOUTUBE_REFRESH_TOKEN, - redirect_uri: process.env.YOUTUBE_REDIRECT_URI, - privacy_status: process.env.YOUTUBE_PRIVACY_STATUS, - category_id: process.env.YOUTUBE_CATEGORY_ID, + client_id: S_YT_CLIENT_ID.value(), + client_secret: S_YT_CLIENT_SECRET.value(), + refresh_token: S_YT_REFRESH_TOKEN.value(), + redirect_uri: S_YT_REDIRECT_URI.value(), + privacy_status: S_YT_PRIVACY_STATUS.value(), + category_id: S_YT_CATEGORY_ID.value(), }).filter(([, value]) => value !== undefined && value !== "") ); +// Compat facultative v1 -> renverra {} en v2 (et on log un warn propre) +const getLegacyYoutubeConfig = () => { + if (typeof functions.config !== "function") { + return {}; + } + + try { + return functions.config()?.youtube || {}; + } catch (error) { + if ( + typeof error?.message === "string" && + error.message.includes("functions.config() is no longer available") + ) { + logger.warn( + "[publishPlaybackToYoutube] functions.config() indisponible, utilisation des secrets (Secret Manager)" + ); + return {}; + } + throw error; + } +}; + const ensureYoutubeConfig = () => { - const firebaseConfig = functions.config()?.youtube || {}; - const envConfig = getEnvYoutubeConfig(); - const cfg = { ...firebaseConfig, ...envConfig }; + // Fusionne (par prudence) l’ancienne config et les secrets actuels + const firebaseConfig = getLegacyYoutubeConfig(); + const secretConfig = getSecretsYoutubeConfig(); + const cfg = { ...firebaseConfig, ...secretConfig }; + const requiredKeys = ["client_id", "client_secret", "refresh_token"]; const missing = requiredKeys.filter((key) => !cfg[key]); if (missing.length) { @@ -48,10 +83,9 @@ const ensureYoutubeConfig = () => { clientId: cfg.client_id, clientSecret: cfg.client_secret, refreshToken: cfg.refresh_token, - redirectUri: - cfg.redirect_uri || "https://developers.google.com/oauthplayground", - defaultPrivacyStatus: cfg.privacy_status || "unlisted", - defaultCategoryId: cfg.category_id || "10", + redirectUri: cfg.redirect_uri, + defaultPrivacyStatus: cfg.privacy_status, + defaultCategoryId: cfg.category_id, }; }; @@ -130,6 +164,15 @@ exports.publishPlaybackToYoutube = onCall( "https://musicland-one.vercel.app/", "https://musicland-d33f9.firebaseapp.com", ], + // Secrets requis pour l’exécution (v2) + secrets: [ + S_YT_CLIENT_ID, + S_YT_CLIENT_SECRET, + S_YT_REFRESH_TOKEN, + S_YT_REDIRECT_URI, + S_YT_PRIVACY_STATUS, + S_YT_CATEGORY_ID, + ], }, async ({ data = {}, auth }) => { const uid = auth?.uid; diff --git a/src/screens/Publishing/PublishYoutube.js b/src/screens/Publishing/PublishYoutube.js index 7b84cfc..93a6a1e 100644 --- a/src/screens/Publishing/PublishYoutube.js +++ b/src/screens/Publishing/PublishYoutube.js @@ -111,7 +111,7 @@ const PublishYoutube = () => { try { const publishCallable = firebase .functions() - .httpsCallable("publishPlaybackToYoutube"); + .httpsCallable("youtube-publishPlaybackToYoutube"); await publishCallable({ projectId }); setTooltip?.({ type: "success", diff --git a/youtube.md b/youtube.md deleted file mode 100644 index f2aea31..0000000 --- a/youtube.md +++ /dev/null @@ -1,24 +0,0 @@ -https://accounts.google.com/o/oauth2/v2/auth -?client_id=305598753437-21ivo6din58aud9dph9bcob06fb52r5n.apps.googleusercontent.com -&redirect_uri=http://localhost:8081 -&response_type=code -&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.upload -&access_type=offline -&prompt=consent - -http://localhost:8081/?code=4/0Ab32j90LMDeJDShWSk1OkXwgbjrHS-qQpyYTlXhH9q3nlV0EJa6cTL-7nI9yOKHoz6rgRA&scope=https://www.googleapis.com/auth/youtube.upload - -curl -X POST https://oauth2.googleapis.com/token \ - -d client_id=305598753437-21ivo6din58aud9dph9bcob06fb52r5n.apps.googleusercontent.com \ - -d client_secret=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 \ - -d code=4/0Ab32j90LMDeJDShWSk1OkXwgbjrHS-qQpyYTlXhH9q3nlV0EJa6cTL-7nI9yOKHoz6rgRA \ - -d grant_type=authorization_code \ - -d redirect_uri=http://localhost:8081 - -{ -"access_token": "ya29.a0ATi6K2uR4DhnmTDl0EN2tvDogwwEwl8SDJLpUzvnZ8LGgOYjgmhqg7MoMM0_iTJR_NBEDPe2LlJDqCFFnIi9s3qRv_zfw_NeTnN-LwUmAyVJkdqSP6GvzQCuZkE6OBuTvaU5b2obk5rHvDOkWXxAb7xjbVTzIBIg8O5VVhJ-VB8VEbTVsSq9bc0ljkbcyBEzm4JdQRwaCgYKAcgSAQ8SFQHGX2MiR1Owf2aiiEBUsU-LDUDgWg0206", -"expires_in": 3599, -"refresh_token": "1//03sy-LDVmCMcFCgYIARAAGAMSNwF-L9IrHwwdBBZvg3Hwun9hxHUx_AsJaa1qeozmtvGtdOXKIRIyKjTp7S_b0igvzM_1A5bLH34", -"scope": "https://www.googleapis.com/auth/youtube.upload", -"token_type": "Bearer" -}