Skip to content
Open
62 changes: 20 additions & 42 deletions src/api/routes/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ router.get('/rso/oauth', async (req, res) => {
});

router.get('/rso/getUserInfo/:token', async (req, res) => {
// Given access token, return player's username, tagline, puuid
// For some reason the puuid returned here can't be decrypted and used for Riot APIs that use puuid as url param
// and also is different from the one given when obtaining player info via americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/{gamename}/{tagline}
const accessToken = req.params.token;
try {
const response = await fetch(
Expand All @@ -412,6 +415,12 @@ router.get('/rso/getUserInfo/:token', async (req, res) => {
if (!response.ok) {
res.status(400).send('could not get user info');
} else {
// Set Access Control Allow Origin response header (fix CORS error on live)
let resHeader = new Headers();
resHeader.append(
'Access-Control-Allow-Origin',
'https://www.lineupx.net',
);
const responseJson = await response.json();
res.send(responseJson);
}
Expand All @@ -420,64 +429,33 @@ router.get('/rso/getUserInfo/:token', async (req, res) => {
}
});

router.get('/rso/oauth', async (req, res) => {
const appCallbackUrl = 'https://www.lineupx.net/game/Valorant';

const accessCode = req.query.code;

const params = new URLSearchParams({
grant_type: 'authorization_code',
code: accessCode,
redirect_uri: appCallbackUrl,
});

try {
const response = await fetch('https://auth.riotgames.com/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization:
'Basic ' +
btoa(
`${process.env.RSO_CLIENT_ID}:${process.env.RSO_CLIENT_SECRET}`,
),
},
body: params,
});
if (!response.ok) {
res.status(400).send('/token request failed!');
} else {
const responseJson = await response.json();
res.send(responseJson);
}
} catch (error) {
console.log('error', error);
}
});

router.get('/rso/getUserInfo/:token', async (req, res) => {
const accessToken = req.params.token;
router.post('/rso/getPuuid', async (req, res) => {
// Given gameName and tagLine, return riot puuid
const { gameName, tagLine } = req.body;
console.log('getPuuid called!');
console.log('Here is gameName: ', gameName);
console.log('Here is tagLine:', tagLine);
try {
// Assuming player's region is americas, otherwise put region into {region}.api.riotgames.com
const response = await fetch(
'https://americas.api.riotgames.com/riot/account/v1/accounts/me',
`https://americas.api.riotgames.com/riot/account/v1/accounts/by-riot-id/${gameName}/${tagLine}`,
{
method: 'GET',
headers: {
Authorization: 'Bearer ' + accessToken,
'X-Riot-Token': process.env.RIOT_DEVELOPER_API_KEY,
},
},
);
if (!response.ok) {
res.status(400).send('could not get user info');
res.status(400).send('could not get puuid');
} else {
const responseJson = await response.json();
res.send(responseJson);
}
} catch (error) {
console.log('error', error);
console.log(error);
}
});

/////////////////////////////////////////////////////////////////////////////
/*

Expand Down
2 changes: 1 addition & 1 deletion src/api/routes/leaderboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ router.get('/leaderboard', async (req, res) => {
_id: user._id,
username: user.username,
ProfilePicture: user.ProfilePicture,
...(userPostCounts[user._id.toString()] || {
...(userPostCounts[user._id?.toString()] || {
totalPosts: 0,
monthlyPosts: 0,
weeklyPosts: 0,
Expand Down
67 changes: 66 additions & 1 deletion src/web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'nprogress/nprogress.css';
import {
Page,
ProfilePage,
RiotProfile,
Valorant,
CS2,
Register,
Expand Down Expand Up @@ -76,6 +77,17 @@ type AuthContextType = {
setSaved: React.Dispatch<React.SetStateAction<string[]>>;
following: FollowingType[];
setFollowing: React.Dispatch<React.SetStateAction<FollowingType[]>>;

puuid: string;
setPuuid: React.Dispatch<React.SetStateAction<string>>;
gameName: string;
setGameName: React.Dispatch<React.SetStateAction<string>>;
tagLine: string;
setTagLine: React.Dispatch<React.SetStateAction<string>>;
RSOAccessToken: string;
setRSOAccessToken: React.Dispatch<React.SetStateAction<string>>;
RSORefreshToken: string;
setRSORefreshToken: React.Dispatch<React.SetStateAction<string>>;
};

export const AuthContext = createContext<AuthContextType | undefined>(
Expand All @@ -99,6 +111,14 @@ function App() {
const [following, setFollowing] = useState<FollowingType[]>([]);
const location = useLocation();

const [RSOAccessTokenC] = useCookies('RSOAccessToken', '');
const [RSORefreshTokenC] = useCookies('RSORefreshToken', '');
const [puuid, setPuuid] = useState('');
const [gameName, setGameName] = useState('');
const [tagLine, setTagLine] = useState('');
const [RSOAccessToken, setRSOAccessToken] = useState('');
const [RSORefreshToken, setRSORefreshToken] = useState('');

// Login users
useEffect(() => {
if (accessTokenC && !accessToken) {
Expand Down Expand Up @@ -127,7 +147,38 @@ function App() {
return error;
});
}
}, [accessToken, refreshToken]);
if (RSOAccessTokenC && !RSOAccessToken) {
// if cookie exists, set auth's rso access token to this cookie
setRSOAccessToken(RSOAccessTokenC);
}
if (RSORefreshTokenC && !RSORefreshToken) {
setRSORefreshToken(RSORefreshTokenC);
}
if (RSOAccessToken && RSORefreshToken) {
axios
.get(`/rso/getUserInfo/${RSOAccessToken}`)
.then((res) => {
setGameName(res.data.gameName);
setTagLine(res.data.tagLine);
// Making this postBody object instead of directly passing into axios.post as second arg works
const postBody = {
gameName: res.data.gameName,
tagLine: res.data.tagLine,
};
axios
.post('/rso/getPuuid', postBody)
.then((resp) => {
setPuuid(resp.data.puuid);
})
.catch((error) => {
return error;
});
})
.catch((error) => {
return error;
}); // .get.then.catch avoids async and await
}
}, [accessToken, refreshToken, RSOAccessToken, RSORefreshToken]);

useEffect(() => {
NProgress.start();
Expand Down Expand Up @@ -164,6 +215,16 @@ function App() {
saved,
setSaved,
setFollowing,
puuid,
gameName,
tagLine,
RSOAccessToken,
RSORefreshToken,
setPuuid,
setGameName,
setTagLine,
setRSOAccessToken,
setRSORefreshToken,
}}
>
<ScrollToTop />
Expand Down Expand Up @@ -201,6 +262,10 @@ function App() {
element={<SearchResults />}
></Route>
<Route path="/user/:id" element={<ProfilePage />}></Route>
<Route
path="/user/riotprofile"
element={<RiotProfile />}
></Route>
<Route path="/user/guest" element={<GuestPage />} />
<Route path="/game/:game/:id" element={<PostPage />}></Route>
<Route path="/post/:game/:id" element={<PostPage />}></Route>
Expand Down
1 change: 1 addition & 0 deletions src/web/src/Components.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Pages
export { default as ProfilePage } from './Pages/user/ProfilePage';
export { default as RiotProfile } from './Pages/user/RiotProfile';
export { default as Page } from './Pages/Page';
export { default as Valorant } from './Pages/game/Valorant/Valorant';
export { default as About } from './Pages/About';
Expand Down
90 changes: 44 additions & 46 deletions src/web/src/Components/global/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext, useState, useEffect } from 'react';
import { useContext, useState } from 'react';
import { AuthContext } from '../../App';
import { useCookies } from '../../hooks';
import { Link, useNavigate, useLocation } from 'react-router-dom';
Expand All @@ -15,33 +15,34 @@ const Header: React.FC = () => {
const [, , deleteAccessCookie] = useCookies('accessToken', '');
const [, , deleteRefreshCookie] = useCookies('refreshToken', '');
const [RSOAccessToken, ,] = useCookies('RSOAccessToken', '');
const [RSORefreshToken, ,] = useCookies('RSORefreshToken', '');
// const [RSORefreshToken, ,] = useCookies('RSORefreshToken', '');
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [puuid, setPuuid] = useState('');
const [gameName, setGameName] = useState('');
const [tagLine, setTagLine] = useState('');
// const [puuid, setPuuid] = useState('');
// const [gameName, setGameName] = useState('');
// const [tagLine, setTagLine] = useState('');

const handleRSOSignIn = () => {
window.location.href = axios.defaults.baseURL + 'rso/signin';
};

const checkRSOSignedIn = async () => {
if (!RSOAccessToken && !RSORefreshToken) return; // if these cookies are empty or don't exist, return
console.log('Cookies:', RSORefreshToken, RSOAccessToken);
try {
const res = await axios.get(`/rso/getUserInfo/${RSOAccessToken}`);
const resData = res.data;
console.log(resData);
setPuuid(resData.puuid);
setGameName(resData.gameName);
setTagLine(resData.tagLine);
RSOAccessToken
? console.log('Access token cookie detected')
: console.log('No cookie');
} catch (error) {
console.log('Error fetching', error);
}
};
// const checkRSOSignedIn = async () => {
//
// if (!RSOAccessToken && !RSORefreshToken) return; // if these cookies are empty or don't exist, return
// // console.log("Cookies:", RSORefreshToken, RSOAccessToken);
// try {
// const res = await axios.get(`/rso/getUserInfo/${RSOAccessToken}`);
// const resData = res.data
// // console.log(resData);
// setPuuid(resData.puuid);
// setGameName(resData.gameName);
// setTagLine(resData.tagLine);
// // (RSOAccessToken ? console.log("Access token cookie detected") : console.log("No cookie"))
// }
//
// catch (error){
// console.log("Error fetching", error);
// }
// }

const logout = async () => {
try {
Expand Down Expand Up @@ -72,11 +73,6 @@ const Header: React.FC = () => {
setIsDropdownOpen(!isDropdownOpen);
};

useEffect(() => {
console.log('this is data:', puuid, tagLine, gameName);
checkRSOSignedIn();
}, [puuid]);

return (
<>
<nav
Expand Down Expand Up @@ -184,10 +180,6 @@ const Header: React.FC = () => {
)}
</div>
</>
) : RSOAccessToken ? (
<div className="rounded-lg px-4 py-2 flex items-center space-x-4 font-bold bg-red-600">
{`${gameName}#${tagLine}`}
</div>
) : (
<div
className="flex items-center space-x-2"
Expand All @@ -205,22 +197,28 @@ const Header: React.FC = () => {
>
Sign up
</Link>
<button
type={'button'}
onClick={handleRSOSignIn}
className={
'bg-red-600 text-white p-2 rounded hover:bg-red-500 text-sm whitespace-nowrap'
}
>
<div className={'flex flex-row gap-2'}>
<img
src={valorantLogo}
alt={'Riot Games'}
className={'w-6 h-6'}
/>
<p>{'Sign in'}</p>
{RSOAccessToken ? (
<div className="rounded-lg px-4 py-2 flex items-center space-x-4 font-bold bg-red-600">
{`${Auth?.gameName}#${Auth?.tagLine}`}
</div>
</button>
) : (
<button
type={'button'}
onClick={handleRSOSignIn}
className={
'bg-red-600 text-white p-2 rounded hover:bg-red-500 text-sm whitespace-nowrap'
}
>
<div className={'flex flex-row gap-2'}>
<img
src={valorantLogo}
alt={'Riot Games'}
className={'w-6 h-6'}
/>
<p>{'Sign in'}</p>
</div>
</button>
)}
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/web/src/Pages/leaderboard/Leaderboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const Leaderboard: React.FC = () => {
children,
}) => (
<Link
to={`/user/${user.username}`}
to={`/user/${user?.username}`}
className="hover:text-blue-400 transition-colors duration-200"
>
{children}
Expand Down
Loading