Skip to content

Commit 35aaf89

Browse files
authored
Merge pull request #32 from oslabs-beta/vicky/connect-users-save-query
vicky/connect-users-save-query
2 parents 3b1fe26 + ade72be commit 35aaf89

11 files changed

+104
-25
lines changed

server/controllers/mysqlData.controller.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,18 @@ const mysqlController = {
300300

301301
//----------Function to save query metrics from database-----------------------------------------------------------------
302302
mysqlSaveQuery: async (req: Request, res: Response, next: NextFunction) => {
303+
// getting user info to save query
304+
const user = req.session.user;
305+
console.log('CHECKING USER MYQQL: ', user);
306+
if (!user) {
307+
return res.status(401).json({ error: 'User not authenticated' });
308+
}
309+
303310
try {
304311
// grab queryString from FE
305312
console.log('REQ QUERY: ', req.body.params);
313+
314+
const userEmail = user.email;
306315
const { query_date, exec_time } = req.body.params.extractedQueryRes;
307316
const { queryString, queryName, hostname, database_name } =
308317
req.body.params.dbValues;
@@ -322,9 +331,10 @@ const mysqlController = {
322331
const formatDateForMySql = date.toISOString().split('T')[0];
323332
console.log('formatted date: ', formatDateForMySql);
324333

325-
const insertQueryStr = `INSERT INTO queries (query, db_link, exec_time, db_name, query_date, name, planning_time, total_cost, actual_total_time, node_type, relation_name, plan_rows, actual_rows, shared_hit_blocks, shared_read_blocks) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`;
334+
const insertQueryStr = `INSERT INTO queries (email, query, db_link, exec_time, db_name, query_date, name, planning_time, total_cost, actual_total_time, node_type, relation_name, plan_rows, actual_rows, shared_hit_blocks, shared_read_blocks) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`;
326335

327336
const [saveQuery]: any = await pool.query(insertQueryStr, [
337+
userEmail,
328338
queryString,
329339
hostname,
330340
exec_time,
@@ -349,6 +359,7 @@ const mysqlController = {
349359
if (saveQuery.affectedRows > 0) {
350360
console.log('saveQuery completed!');
351361
res.locals.savedQuery = [
362+
userEmail,
352363
queryString,
353364
hostname,
354365
exec_time,

server/controllers/oauth.controller.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,24 @@ interface GlobalError {
99
message: string | { err: string };
1010
}
1111

12+
interface GitHubUser {
13+
id: number;
14+
url: string; // this is equivalent to the user email, is stored in the db as well
15+
login: string;
16+
type: string;
17+
}
18+
1219
export const getAccesToken: RequestHandler = (
1320
req: Request,
1421
res: Response,
1522
next: NextFunction
1623
) => {
1724
log.info('[oauthCtrl - getAccToken] Getting user access token...');
18-
if (typeof req.session.user === 'string') return res.redirect('/api/me');
25+
// checks if user email already exists
26+
if (req.session.user?.email) {
27+
return res.redirect('/api/me');
28+
}
29+
1930
type code = string;
2031
type state = string | null;
2132
const { code, state } = req.body;
@@ -115,7 +126,7 @@ export const getUserInfo: RequestHandler = async (
115126
try {
116127
let data: any;
117128
// For Github Oauth
118-
let userInfo: {};
129+
let userInfo: GitHubUser;
119130

120131
if (type === 'GITHUB') {
121132
data = await fetch('https://api.github.com/user', {
@@ -129,6 +140,17 @@ export const getUserInfo: RequestHandler = async (
129140

130141
userInfo = await data.json();
131142
userInfo = { ...userInfo, type: 'github' };
143+
144+
console.log('userInfo from Github: ', userInfo);
145+
if (req.session) {
146+
req.session.user = {
147+
id: userInfo.id,
148+
email: userInfo.url,
149+
username: userInfo.login,
150+
type: 'github',
151+
};
152+
}
153+
console.log('checking req.session.user: ', req.session.user);
132154
} else {
133155
throw new Error(
134156
`[oauthCtrl - getUserInfo] middleware error (GitHub): Unexpected response status ${data.status}`

server/controllers/postgresData.controller.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,6 @@ const postgresController = {
233233
};
234234
const formattedDate = `Date Run: ${now.toLocaleString('en-US', options)}`;
235235

236-
/************* mysql querymetrics db insert for saved query page retrieval ******/
237-
// creating insert query for mysql query metrics db
238-
//Todo: figure out how to get the email from the session, if an user logs in and then tests query performance
239-
//const email = 'https://api.github.com/users/reva2024';
240-
//const db_link = 'postgresql://postgres.gcfszuopjvbjtllgmenw:[email protected]:6543/postgres';
241-
//const db_name = 'dbSpy';
242-
243236
// Send query name, query string, date, and execution time on response
244237
res.locals.metrics = [namedQuery, queryStr, formattedDate, executionTime];
245238
res.locals.otherMetrics = otherMetrics;
@@ -255,10 +248,17 @@ const postgresController = {
255248

256249
//----------Function to save query metrics after running query-----------------------------------------------------------------
257250
postgresSaveQuery: async (req: Request, res: Response, next: NextFunction) => {
251+
// getting user info to save query
252+
const user = req.session.user;
253+
if (!user) {
254+
return res.status(401).json({ error: 'User not authenticated' });
255+
}
256+
258257
try {
259258
console.log('REACHED postgresSaveMetrics MIDDLEWARE');
260259
console.log('REQ BODY: ', req.body.params);
261260

261+
const userEmail = user.email;
262262
const { query_date, exec_time } = req.body.params.extractedQueryRes;
263263
const { queryString, queryName, hostname, database_name } =
264264
req.body.params.dbValues;
@@ -279,10 +279,11 @@ const postgresController = {
279279
const formatDateForMySql = date.toISOString().split('T')[0];
280280
console.log('formatted date: ', formatDateForMySql);
281281

282-
const insertQueryStr = `INSERT INTO queries (query, db_link, exec_time, db_name, query_date, name, planning_time, total_cost, actual_total_time, node_type, relation_name, plan_rows, actual_rows, shared_hit_blocks, shared_read_blocks) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`;
282+
const insertQueryStr = `INSERT INTO queries (email, query, db_link, exec_time, db_name, query_date, name, planning_time, total_cost, actual_total_time, node_type, relation_name, plan_rows, actual_rows, shared_hit_blocks, shared_read_blocks) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`;
283283

284284
//connect to mysql pool imported from userModel and send the query to update table
285285
const [savingQuery]: any = await pool.query(insertQueryStr, [
286+
userEmail,
286287
queryString,
287288
hostname,
288289
exec_time,
@@ -307,6 +308,7 @@ const postgresController = {
307308
if (savingQuery.affectedRows > 0) {
308309
console.log('savingQuery completed!');
309310
res.locals.savedQuery = [
311+
userEmail,
310312
queryString,
311313
hostname,
312314
exec_time,

server/controllers/save.controller.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,20 @@ interface GlobalError {
3232
const saveController = {
3333
getSavedQueries: async (req: Request, res: Response, next: NextFunction) => {
3434
log.info('[saveCtrl - getSavedQueries] Beginning to load saved queries');
35+
const user = req.session.user;
36+
if (!user) {
37+
return res.status(401).json({ error: 'User not authenticated' });
38+
}
39+
3540
try {
3641
// query to get all necessary data to the FE
37-
// TODO - add in user data to filter per user
38-
const getQueries: string = `SELECT name, query, query_date, exec_time, planning_time, total_cost, actual_total_time, node_type, relation_name, plan_rows, actual_rows, shared_hit_blocks, shared_read_blocks FROM queries ORDER BY id DESC`;
39-
const queryVal = await pool.query(getQueries);
42+
const userEmail = user.email;
43+
const getQueries: string = `SELECT name, query, query_date, exec_time, planning_time, total_cost, actual_total_time, node_type, relation_name, plan_rows, actual_rows, shared_hit_blocks, shared_read_blocks FROM queries WHERE email = ? ORDER BY id DESC`;
44+
const queryVal = await pool.query(getQueries, [userEmail]);
4045
res.locals.savedQueries = queryVal;
4146
return next();
4247
} catch (err) {
48+
console.error('getSavedQueries ERROR:', err);
4349
return next({
4450
log: 'An error occurred in saveController.getSavedQueries',
4551
message: 'Something went wrong in the loading process',

server/controllers/sessionController.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ config();
88

99
declare module 'express-session' {
1010
interface SessionData {
11-
user: string;
11+
user?: {
12+
id: number | 0; // github oauth will provide id, 0 will be if id doesn't exist (n/a)
13+
email: string;
14+
username: string;
15+
type: string;
16+
};
1217
email: string;
1318
}
1419
}
@@ -46,7 +51,7 @@ export const setJwtToken: RequestHandler = async (
4651

4752
// store access token and email in the session
4853
// getCurrentUser uses accessToken, saveSchema and retrieveSchema use the email
49-
req.session.user = accessToken;
54+
req.session.accessToken = accessToken;
5055
req.session.email = email;
5156

5257
return next();
@@ -57,8 +62,8 @@ export const setJwtToken: RequestHandler = async (
5762
};
5863

5964
export const getCurrentUser: RequestHandler = (req, res) => {
60-
if (req?.session?.user) {
61-
const accessToken = req.session.user;
65+
if (req?.session?.accessToken) {
66+
const accessToken = req.session.accessToken;
6267

6368
jwt.verify(
6469
accessToken as string,

server/controllers/user.controller.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,16 @@ export const verifyUser: RequestHandler = async (
206206
email: foundUser[0][0].email,
207207
};
208208

209+
if (req.session) {
210+
req.session.user = {
211+
id: 0,
212+
email: res.locals.userInfo.email,
213+
username: res.locals.userInfo.name,
214+
type: 'auth',
215+
};
216+
}
217+
console.log('checking req.session.user: ', req.session.user);
218+
209219
return next();
210220
} else {
211221
log.error('[userCtrl - verifyUser] Username/Password do not match');
@@ -226,6 +236,13 @@ export const verifyUser: RequestHandler = async (
226236
}
227237
};
228238

239+
export const isAuthenticated: RequestHandler = (req, res, next) => {
240+
if (!req.session.user) {
241+
return res.status(401).json({ error: 'Not logged in' });
242+
}
243+
return next();
244+
};
245+
229246
// Save currentSchema into database
230247
export const saveSchema: RequestHandler = async (
231248
req: Request,

server/routes/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ declare module 'express-session' {
3535
logging?: boolean;
3636
db_type?: string;
3737
file_path?: string;
38+
user?: {
39+
id: number;
40+
email: string;
41+
username: string;
42+
type: string;
43+
};
44+
accessToken?: string;
3845
}
3946
}
4047

server/routes/mysql.router.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Router, Response, Request } from 'express';
22
import mysqlController from '../controllers/mysqlData.controller';
3+
import { isAuthenticated } from '../controllers/user.controller';
34

45
const mysqlRouter = Router();
56

@@ -18,6 +19,7 @@ mysqlRouter.get(
1819

1920
mysqlRouter.post(
2021
'/save-query',
22+
isAuthenticated,
2123
mysqlController.mysqlSaveQuery,
2224
(_req: Request, res: Response) => {
2325
return res.status(200).json(res.locals.savedQuery);

server/routes/postgres.router.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Router, Response, Request } from 'express';
22
import postgresController from '../controllers/postgresData.controller';
3+
import { isAuthenticated } from '../controllers/user.controller';
34

45
const postgresRouter = Router();
56

@@ -22,6 +23,7 @@ postgresRouter.get(
2223

2324
postgresRouter.post(
2425
'/save-query',
26+
isAuthenticated,
2527
postgresController.postgresSaveQuery,
2628
(_req: Request, res: Response) => {
2729
return res.status(200).json(res.locals.savedQuery);

server/routes/save.router.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import { Router, Response, Request } from 'express';
44
import bodyParser from 'body-parser';
55
import saveController from '../controllers/save.controller';
6+
import { isAuthenticated } from '../controllers/user.controller';
7+
68
const saveRouter = Router();
79

810
// Apply bodyParser with a larger limit
@@ -13,6 +15,7 @@ const saveRouter = Router();
1315
//Load Saved Queries
1416
saveRouter.get(
1517
'/saved-queries',
18+
isAuthenticated,
1619
saveController.getSavedQueries,
1720
(_req: Request, res: Response) => {
1821
return res.status(200).json(res.locals.savedQueries);

src/pages/ViewSavedQueries.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,17 @@ const ViewSavedQueries: React.FC = () => {
5454
<>
5555
<div className="justify-space-around flex-auto justify-end border-2 border-black pr-2">
5656
<FeatureTab />
57-
<div className="ml-20 pt-20 text-center">
58-
<h1 className="mb-12 text-5xl font-bold tracking-tight text-yellow-400">
59-
Saved Queries
60-
</h1>
61-
</div>
6257
<div
6358
className={`h-screen transition-all duration-300 ${
6459
toggleClicked ? 'ml-16' : 'ml-64'
6560
}`}
6661
>
67-
{/* this wrap aligns the title 'Queries Saved w/ the table together */}
62+
<h1 className="flex items-center justify-center pt-20 text-5xl font-bold tracking-tight text-slate-700 dark:text-white">
63+
Saved Queries
64+
</h1>
65+
{/* this wrap aligns the title 'Saved Queries w/ the table together */}
6866
<div className="mt-4 flex gap-x-8">
69-
{savedQueries.length > 0 && (
67+
{savedQueries.length > 0 ? (
7068
<div className="mt-8 w-full max-w-[1300px] shrink-0 overflow-x-auto px-4 text-white">
7169
<table className="min-w-full table-fixed border-collapse border border-white text-white">
7270
<thead>
@@ -164,6 +162,10 @@ const ViewSavedQueries: React.FC = () => {
164162
</tbody>
165163
</table>
166164
</div>
165+
) : (
166+
<div className="flex h-full w-full items-center justify-center text-white">
167+
No queries saved.
168+
</div>
167169
)}
168170
</div>
169171
</div>

0 commit comments

Comments
 (0)