diff --git a/app.js b/app.js index 9513f5f..003770f 100644 --- a/app.js +++ b/app.js @@ -51,6 +51,7 @@ app.get("/", (req, res) => { res.send("๐Ÿš€ Server is running!"); }); + // โœ… API ๋ผ์šฐํŠธ ์„ค์ • (โšก ์ถฉ๋Œ ๋ฐฉ์ง€: `/api` ๊ฒฝ๋กœ๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€) app.use("/api", userRoutes); // ์‚ฌ์šฉ์ž ๊ด€๋ฆฌ API app.use("/api/bottle", bottleMessageRoutes); // ์œ ๋ฆฌ๋ณ‘ ํŽธ์ง€ ๊ด€๋ จ API @@ -68,4 +69,5 @@ app.use((req, res, next) => { // โœ… ์„œ๋ฒ„ ์‹คํ–‰ app.listen(PORT, '0.0.0.0', () => { console.log(`๐Ÿš€ Server is running on port ${PORT}`); -}); \ No newline at end of file +}); + diff --git a/controllers/authController.js b/controllers/authController.js index 9ff44d0..ab5900f 100644 --- a/controllers/authController.js +++ b/controllers/authController.js @@ -1,9 +1,84 @@ +// import dotenv from 'dotenv'; +// import { google } from 'googleapis'; +// import fs from 'fs'; + +// dotenv.config(); + +// // Google OAuth 2.0 ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ +// const oAuth2Client = new google.auth.OAuth2( +// process.env.GOOGLE_CLIENT_ID, +// process.env.GOOGLE_CLIENT_SECRET, +// process.env.GOOGLE_REDIRECT_URI +// ); + +// // Google ๋กœ๊ทธ์ธ URL ์ƒ์„ฑ (ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์š”์ฒญ ์‹œ ๋กœ๊ทธ์ธ url์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅ) +// export const getAuthURL = (req, res) => { +// try { +// const authUrl = oAuth2Client.generateAuthUrl({ +// access_type: 'offline', // refresh_token์„ ๋ฐ›๊ธฐ ์œ„ํ•ด 'offline' ์„ค์ • +// scope: ['https://www.googleapis.com/auth/drive.file'], +// prompt: 'consent', // ํ•ญ์ƒ refresh_token์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ • +// }); + +// console.log("Generated Auth URL:", authUrl); +// // res.json({ authUrl }); // ํ”„๋ก ํŠธ์—”๋“œ์— ๋กœ๊ทธ์ธ URL ๋ฐ˜ํ™˜ ๋ฐฉ์‹ +// res.redirect(authUrl); // Google ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ž๋™ ์ด๋™ ๋ฐฉ์‹ +// } catch (error) { +// console.error("Error generating auth URL:", error); +// res.status(500).json({ error: 'Failed to generate authentication URL' }); +// } +// }; + +// // Google OAuth ์ฝœ๋ฐฑ ์ฒ˜๋ฆฌ (ํ† ํฐ ์ €์žฅ) +// export const handleOAuthCallback = async (req, res) => { +// try { +// const { code } = req.query; +// if (!code) return res.status(400).json({ error: 'Authorization code is missing' }); + +// // ์ธ์ฆ ์ฝ”๋“œ๋กœ Access Token & Refresh Token ์š”์ฒญ +// const { tokens } = await oAuth2Client.getToken(code); +// oAuth2Client.setCredentials(tokens); + +// console.log("Received Tokens:", tokens); + +// // refresh_token ์ €์žฅ (์ž๋™์œผ๋กœ .env์˜ GOOGLE_REFRESH_TOKEN ํ•„๋“œ ์—…๋ฐ์ดํŠธ) +// if (tokens.refresh_token) { +// const envFilePath = '.env'; +// let envData = fs.readFileSync(envFilePath, 'utf8'); + +// // ๊ธฐ์กด GOOGLE_REFRESH_TOKEN์ด ์žˆ์œผ๋ฉด ์—…๋ฐ์ดํŠธ, ์—†์œผ๋ฉด ์ถ”๊ฐ€ +// if (envData.includes('GOOGLE_REFRESH_TOKEN=')) { +// envData = envData.replace(/^GOOGLE_REFRESH_TOKEN=.*$/m, `GOOGLE_REFRESH_TOKEN=${tokens.refresh_token}`); +// } else { +// envData += `\nGOOGLE_REFRESH_TOKEN=${tokens.refresh_token}\n`; +// } + +// fs.writeFileSync(envFilePath, envData, 'utf8'); +// console.log("Refresh Token saved to .env"); +// } + +// // Access Token์„ ํ”„๋ก ํŠธ์—”๋“œ์— ๋ฐ˜ํ™˜ +// res.json({ +// message: "Authorization successful", +// accessToken: tokens.access_token, +// refreshToken: tokens.refresh_token || "No new refresh token received", +// expiresIn: tokens.expiry_date, +// }); + +// } catch (error) { +// console.error("OAuth Callback Error:", error); +// res.status(500).json({ error: "Authorization failed", details: error.message }); +// } +// }; + import dotenv from 'dotenv'; import { google } from 'googleapis'; import fs from 'fs'; dotenv.config(); +let accessToken = null; // Access Token ์ €์žฅ ๋ณ€์ˆ˜ + // Google OAuth 2.0 ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ const oAuth2Client = new google.auth.OAuth2( process.env.GOOGLE_CLIENT_ID, @@ -11,18 +86,17 @@ const oAuth2Client = new google.auth.OAuth2( process.env.GOOGLE_REDIRECT_URI ); -// Google ๋กœ๊ทธ์ธ URL ์ƒ์„ฑ (ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์š”์ฒญ ์‹œ ๋กœ๊ทธ์ธ url์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ • ๊ฐ€๋Šฅ) +// Google ๋กœ๊ทธ์ธ URL ์ƒ์„ฑ export const getAuthURL = (req, res) => { try { const authUrl = oAuth2Client.generateAuthUrl({ - access_type: 'offline', // refresh_token์„ ๋ฐ›๊ธฐ ์œ„ํ•ด 'offline' ์„ค์ • + access_type: 'offline', scope: ['https://www.googleapis.com/auth/drive.file'], - prompt: 'consent', // ํ•ญ์ƒ refresh_token์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์„ค์ • + prompt: 'consent', }); console.log("Generated Auth URL:", authUrl); - // res.json({ authUrl }); // ํ”„๋ก ํŠธ์—”๋“œ์— ๋กœ๊ทธ์ธ URL ๋ฐ˜ํ™˜ ๋ฐฉ์‹ - res.redirect(authUrl); // Google ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ž๋™ ์ด๋™ ๋ฐฉ์‹ + res.redirect(authUrl); } catch (error) { console.error("Error generating auth URL:", error); res.status(500).json({ error: 'Failed to generate authentication URL' }); @@ -35,18 +109,17 @@ export const handleOAuthCallback = async (req, res) => { const { code } = req.query; if (!code) return res.status(400).json({ error: 'Authorization code is missing' }); - // ์ธ์ฆ ์ฝ”๋“œ๋กœ Access Token & Refresh Token ์š”์ฒญ const { tokens } = await oAuth2Client.getToken(code); oAuth2Client.setCredentials(tokens); + accessToken = tokens.access_token; // Access Token ์ €์žฅ + console.log("Received Tokens:", tokens); - // refresh_token ์ €์žฅ (์ž๋™์œผ๋กœ .env์˜ GOOGLE_REFRESH_TOKEN ํ•„๋“œ ์—…๋ฐ์ดํŠธ) if (tokens.refresh_token) { const envFilePath = '.env'; let envData = fs.readFileSync(envFilePath, 'utf8'); - // ๊ธฐ์กด GOOGLE_REFRESH_TOKEN์ด ์žˆ์œผ๋ฉด ์—…๋ฐ์ดํŠธ, ์—†์œผ๋ฉด ์ถ”๊ฐ€ if (envData.includes('GOOGLE_REFRESH_TOKEN=')) { envData = envData.replace(/^GOOGLE_REFRESH_TOKEN=.*$/m, `GOOGLE_REFRESH_TOKEN=${tokens.refresh_token}`); } else { @@ -57,7 +130,6 @@ export const handleOAuthCallback = async (req, res) => { console.log("Refresh Token saved to .env"); } - // Access Token์„ ํ”„๋ก ํŠธ์—”๋“œ์— ๋ฐ˜ํ™˜ res.json({ message: "Authorization successful", accessToken: tokens.access_token, @@ -70,3 +142,11 @@ export const handleOAuthCallback = async (req, res) => { res.status(500).json({ error: "Authorization failed", details: error.message }); } }; + +// ์ €์žฅ๋œ Access Token ๋ฐ˜ํ™˜ +export const getAccessToken = (req, res) => { + if (!accessToken) { + return res.status(400).json({ error: "No access token available. Please authenticate first." }); + } + res.json({ accessToken }); +}; diff --git a/models/database.js b/models/database.js index 2940b6e..6e26a21 100644 --- a/models/database.js +++ b/models/database.js @@ -8,5 +8,4 @@ export const db = mysql.createPool({ user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, -}); - +}); \ No newline at end of file diff --git a/routes/authRoutes.js b/routes/authRoutes.js index 02db97e..1b819d4 100644 --- a/routes/authRoutes.js +++ b/routes/authRoutes.js @@ -1,12 +1,26 @@ -import { getAuthURL, handleOAuthCallback } from "../controllers/authController.js"; +// import { getAuthURL, handleOAuthCallback } from "../controllers/authController.js"; +// import express from "express"; + +// const authRoutes = express.Router(); + +// // Google ๋กœ๊ทธ์ธ URL ์ƒ์„ฑ +// authRoutes.get("/", getAuthURL); + +// // Google OAuth ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ์ฝœ๋ฐฑ +// authRoutes.get("/callback", handleOAuthCallback); + +// // ํ”„๋ก ํŠธ์—์„œ OAuth ์ธ์ฆ ํ›„ ๋ฐ›์€ code๋ฅผ ๋ฐฑ์—”๋“œ์— ์ „๋‹ฌํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ +// authRoutes.get("/token"); + +// export default authRoutes; + +import { getAuthURL, handleOAuthCallback, getAccessToken } from "../controllers/authController.js"; import express from "express"; const authRoutes = express.Router(); -// Google ๋กœ๊ทธ์ธ URL ์ƒ์„ฑ authRoutes.get("/", getAuthURL); - -// Google OAuth ๋กœ๊ทธ์ธ ์„ฑ๊ณต ํ›„ ์ฝœ๋ฐฑ authRoutes.get("/callback", handleOAuthCallback); +authRoutes.get("/token", getAccessToken); // ์ƒˆ ํ•จ์ˆ˜ ์ถ”๊ฐ€ export default authRoutes;