diff --git a/backend/_dot_vercel_copy/output/functions/api.func/router.js b/backend/_dot_vercel_copy/output/functions/api.func/router.js index 8c9c43dd..352bb707 100644 --- a/backend/_dot_vercel_copy/output/functions/api.func/router.js +++ b/backend/_dot_vercel_copy/output/functions/api.func/router.js @@ -9,7 +9,7 @@ import { default as patInfo } from "./api-renamed/status/pat-info.js"; import { default as statusUp } from "./api-renamed/status/up.js"; import { default as authenticate } from "./api-renamed/authenticate.js"; import { default as deleteUser } from "./api-renamed/delete-user.js"; -import { default as privateAccess } from "./api-renamed/private-access.js"; +import { default as userAccess } from "./api-renamed/user-access.js"; import { default as downgrade } from "./api-renamed/downgrade.js"; export default async (req, res) => { @@ -61,8 +61,8 @@ export default async (req, res) => { case "/api/delete-user": await deleteUser(req, res); break; - case "/api/private-access": - await privateAccess(req, res); + case "/api/user-access": + await userAccess(req, res); break; case "/api/downgrade": await downgrade(req, res); diff --git a/backend/api-renamed/downgrade.js b/backend/api-renamed/downgrade.js index 34d7714e..bf240be0 100644 --- a/backend/api-renamed/downgrade.js +++ b/backend/api-renamed/downgrade.js @@ -1,9 +1,9 @@ -import { hasPrivateAccess, getUserToken, deleteUser } from "../src/common/database.js"; +import { getUserAccess, deleteUser } from "../src/common/database.js"; import axios from "axios"; import { logger } from "../src/index.js"; export default async (req, res) => { - // We could optimize this method by doing all 3 database operations in one statement, using "DELETE ... RETURNING ..." + // We could optimize this method by doing both database operations in one statement, using "DELETE ... RETURNING ..." const { user_key } = req.query; if (!user_key) { @@ -22,19 +22,18 @@ export default async (req, res) => { ); } - // verify that user has private access - const privateAccess = await hasPrivateAccess(user_key); - if (!privateAccess) { - res.statusCode = 400; - res.send("user does not have private access"); + // get token and private access status + const userAccess = await getUserAccess(user_key); + if (!userAccess) { + res.statusCode = 404; + res.send("user not found"); return; } - // get access token for user - const token = await getUserToken(user_key); - if (!token) { - res.statusCode = 404; - res.send("user not found"); + // verify that user has private access + if (!userAccess.privateAccess) { + res.statusCode = 400; + res.send("user does not have private access"); return; } @@ -47,7 +46,7 @@ export default async (req, res) => { username: process.env.OAUTH_CLIENT_ID, password: process.env.OAUTH_CLIENT_SECRET, }, - data: { access_token: token }, + data: { access_token: userAccess.token }, headers: { Accept: "application/vnd.github+json", }, diff --git a/backend/api-renamed/private-access.js b/backend/api-renamed/user-access.js similarity index 50% rename from backend/api-renamed/private-access.js rename to backend/api-renamed/user-access.js index c7957164..cb5720ea 100644 --- a/backend/api-renamed/private-access.js +++ b/backend/api-renamed/user-access.js @@ -1,5 +1,5 @@ import { logger } from "../src/common/utils.js"; -import { hasPrivateAccess } from "../src/common/database.js"; +import { getUserAccess } from "../src/common/database.js"; /** * @param {any} req The request. @@ -8,8 +8,18 @@ import { hasPrivateAccess } from "../src/common/database.js"; export default async (req, res) => { const { user_key } = req.query; try { - const result = await hasPrivateAccess(user_key); - res.send(result); + const result = await getUserAccess(user_key); + + if (!result) { + res.statusCode = 404; + res.send("user not found"); + return; + } + + res.send({ + privateAccess: result.privateAccess, + token: result.token + }); } catch (err) { logger.error(err); res.send("Something went wrong: " + err.message); diff --git a/backend/src/common/database.js b/backend/src/common/database.js index 20572c4e..cfe92d0a 100644 --- a/backend/src/common/database.js +++ b/backend/src/common/database.js @@ -192,18 +192,18 @@ export async function deleteUser(userKey) { } /** - * Checks if private_access is true for the given user_key. + * Fetches token and private access status for a given user_key. * - * @param {string} userKey user key of the user to be checked - * @returns {Promise} true if private_access is true, false otherwise + * @param {string} userKey user key of the user to fetch information for + * @returns {Promise<{token: string, privateAccess: boolean} | null>} token and private access status, or null if user not found */ -export async function hasPrivateAccess(userKey) { +export async function getUserAccess(userKey) { if (!pool) { return null; } const query = ` - SELECT private_access + SELECT access_token, private_access FROM authenticated_users WHERE user_key = $1 LIMIT 1 @@ -213,39 +213,10 @@ export async function hasPrivateAccess(userKey) { if (rows.length === 0) { return null; } - return rows[0].private_access; - } catch (err) { - if (err.code === "42P01") { - return null; - } else { - throw err; - } - } -} - -/** - * Fetches access_token for a given user_key. - * - * @param {string} userKey user key of the user to fetch token for - * @returns Returns user key if found, null otherwise - */ -export async function getUserToken(userKey) { - if (!pool) { - return null; - } - - const query = ` - SELECT access_token - FROM authenticated_users - WHERE user_key = $1 - LIMIT 1 - `; - try { - const { rows } = await pool.query(query, [userKey]); - if (rows.length === 0) { - return null; - } - return rows[0].access_token; + return { + token: rows[0].access_token, + privateAccess: rows[0].private_access + }; } catch (err) { if (err.code === "42P01") { return null; diff --git a/frontend/frontend/src/api/user.js b/frontend/frontend/src/api/user.js index ca42b25e..e81bfa81 100644 --- a/frontend/frontend/src/api/user.js +++ b/frontend/frontend/src/api/user.js @@ -30,12 +30,13 @@ const authenticate = async (code, privateAccess, userKey) => { const getUserMetadata = async (userKey) => { try { - const fullUrl = `https://${HOST}/api/private-access?user_key=${userKey}`; + const fullUrl = `https://${HOST}/api/user-access?user_key=${userKey}`; + // if this returns a 404/400, will the _logout() in AppTrends.js be triggered successfully? const result = await axios.get(fullUrl); return result.data; } catch (error) { console.error(error); - return ''; + return null; } }; diff --git a/frontend/frontend/src/pages/App/AppTrends.js b/frontend/frontend/src/pages/App/AppTrends.js index f437e634..6dc10974 100644 --- a/frontend/frontend/src/pages/App/AppTrends.js +++ b/frontend/frontend/src/pages/App/AppTrends.js @@ -9,7 +9,7 @@ import { } from 'react-router-dom'; import { logout as _logout, - setPrivateAccess as _setPrivateAccess, + setUserAccess as _setUserAccess, } from '../../redux/actions/userActions'; import Header from './Header'; @@ -56,16 +56,17 @@ function App() { const isAuthenticated = userId && userId.length > 0; const dispatch = useDispatch(); - const setPrivateAccess = (access) => dispatch(_setPrivateAccess(access)); + const setUserAccess = (access) => + dispatch(_setUserAccess(access.token, access.privateAccess)); useEffect(() => { async function getPrivateAccess() { if (userKey && userKey.length > 0) { - const privateAccess = await getUserMetadata(userKey); - if (privateAccess === null) { + const userAccess = await getUserMetadata(userKey); + if (userAccess === null) { dispatch(_logout()); } else { - setPrivateAccess(privateAccess); + setUserAccess(userAccess); } } } diff --git a/frontend/frontend/src/pages/App/AppWrapped.js b/frontend/frontend/src/pages/App/AppWrapped.js index 38fcf73d..4972b180 100644 --- a/frontend/frontend/src/pages/App/AppWrapped.js +++ b/frontend/frontend/src/pages/App/AppWrapped.js @@ -8,7 +8,7 @@ import { SignUpScreen } from '../Auth'; import { SelectUserScreen, WrappedScreen } from '../Wrapped'; import { NoMatchScreen } from '../Misc'; -import { setPrivateAccess as _setPrivateAccess } from '../../redux/actions/userActions'; +import { setUserAccess as _setPrivateAccess } from '../../redux/actions/userActions'; import { getUserMetadata } from '../../api'; import Footer from './Footer'; diff --git a/frontend/frontend/src/pages/Home/Home.js b/frontend/frontend/src/pages/Home/Home.js index 27149dfd..ad590ca6 100644 --- a/frontend/frontend/src/pages/Home/Home.js +++ b/frontend/frontend/src/pages/Home/Home.js @@ -151,6 +151,7 @@ const HomeScreen = () => { const ghToken = prompt('input GitHub token:'); process.env['PAT_1'] = ghToken; await testEndpoint('/api/wakatime?username=ffflabs'); + await testEndpoint('/api/wakatime?username=ffflabsASDF'); console.log('PAT_1: ', process.env.PAT_1); // console.log(router); /* diff --git a/frontend/frontend/src/redux/actions/userActions.js b/frontend/frontend/src/redux/actions/userActions.js index 7a34d6dc..92d9094e 100644 --- a/frontend/frontend/src/redux/actions/userActions.js +++ b/frontend/frontend/src/redux/actions/userActions.js @@ -1,6 +1,6 @@ export const LOGIN = 'LOGIN'; export const LOGOUT = 'LOGOUT'; -export const SET_PRIVATE_ACCESS = 'SET_PRIVATE_ACCESS'; +export const SET_USER_ACCESS = 'SET_USER_ACCESS'; export function login(userId, userKey) { return { type: LOGIN, payload: { userId, userKey } }; @@ -10,6 +10,9 @@ export function logout() { return { type: LOGOUT, payload: {} }; } -export function setPrivateAccess(privateAccess) { - return { type: SET_PRIVATE_ACCESS, payload: { privateAccess } }; +export function setUserAccess(token, privateAccess) { + return { + type: SET_USER_ACCESS, + payload: { token: token, privateAccess: privateAccess }, + }; } diff --git a/frontend/frontend/src/redux/reducers/user.js b/frontend/frontend/src/redux/reducers/user.js index 9ca13db8..55f35611 100644 --- a/frontend/frontend/src/redux/reducers/user.js +++ b/frontend/frontend/src/redux/reducers/user.js @@ -22,11 +22,13 @@ export default (state = initialState, action) => { return { userId: null, userKey: null, + token: null, privateAccess: null, }; - case types.SET_PRIVATE_ACCESS: + case types.SET_USER_ACCESS: return { ...state, + token: action.payload.token, privateAccess: action.payload.privateAccess, }; default: diff --git a/frontend/frontend/src/wakatime-override.js b/frontend/frontend/src/wakatime-override.js index 71ddf114..f4ac9028 100644 --- a/frontend/frontend/src/wakatime-override.js +++ b/frontend/frontend/src/wakatime-override.js @@ -10,7 +10,7 @@ const fetchWakatimeStats = async ({ username, api_domain }) => { `https://${HOST}/api/wakatime-proxy?username=${username}`, ); - return data.data; + return data; }; export { fetchWakatimeStats };