Skip to content

Commit

Permalink
Merge pull request #42 from dheffer/Setup-JWT-OAuth-all-requests
Browse files Browse the repository at this point in the history
Setup jwt, auth all requests
  • Loading branch information
BrandonJohnson97 authored Apr 13, 2024
2 parents c3146a9 + 7c062c4 commit 9402bcb
Show file tree
Hide file tree
Showing 13 changed files with 789 additions and 413 deletions.
866 changes: 569 additions & 297 deletions backend/src/app.js

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions frontend/src/pages/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import '../App.css';

export const Login = () => {
const [googleOauthURL, setGoogleOauthURL] = useState('');
const [searchParams] = useSearchParams();
const [searchParams, setSearchParams] = useSearchParams();
const [error, setError] = useState('');

let navigate = useNavigate();

useEffect(() => {
useEffect( () => {
fetchGoogleOauthURL();
}, []);

Expand All @@ -26,16 +26,16 @@ export const Login = () => {
});
};

useEffect(() => {
useEffect( () => {
const token = searchParams.get('token');
if (token) {
if(token) {
localStorage.setItem('token', token);
navigate('/garage');
}
}, [searchParams, navigate]);
}, [searchParams, navigate])

const handleLogin = () => {
if (googleOauthURL) {
if(googleOauthURL) {
window.location.href = googleOauthURL;
} else {
setError('Google OAuth URL not found');
Expand All @@ -55,4 +55,4 @@ export const Login = () => {
);
};

export default Login;
export default Login;
32 changes: 17 additions & 15 deletions frontend/src/pages/NavBar.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {Nav, Navbar} from "react-bootstrap";
import { Nav, Navbar } from "react-bootstrap";
import Container from "react-bootstrap/Container";
import React from "react";
import {useState, useEffect} from 'react';
import React, { useState, useEffect } from 'react';
import Settings from "./Settings";
import '../App.css';
import Button from "react-bootstrap/Button";
import { GearFill } from 'react-bootstrap-icons';
import '../App.css';
Expand All @@ -12,38 +12,40 @@ function NavBar() {

useEffect(() => {
const fetchUser = async () => {
try {
try{
const token = localStorage.getItem('token');
if (token) {
if(token) {
const response = await fetch('/api/user', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
if(response.ok){
const data = await response.json();
console.log("USERNAME DATA: ", data.name);
console.log("USERNAME DATA: " + data.name);
setUser(data.name);
} else {

}
else {
console.error("User not found");
}
}
} catch (error) {
}
catch (error) {
console.log(error);
}
};
fetchUser();
}, []);

return (
<Navbar expand="lg" className="bg-body-tertiary navbar-bottom-margin" sticky="top">
<Container>
<Navbar.Brand href="/garage" style={{ display: 'flex', alignItems: 'center' }}>
<span className="drive">Drive</span><span className="line">line</span>
<Navbar.Brand href="/garage" style={{ display: 'flex', alignItems: 'flex-start', marginDown: '35px' }}>
<span className="drive" style={{ display: 'flex', alignItems: 'flex-start', marginTop: '15px' }}>Drive</span><span className="line" style={{ display: 'flex', alignItems: 'flex-start', marginTop: '15px' }}>line</span>
</Navbar.Brand>
<Navbar.Toggle/>
<Navbar.Toggle />
<Navbar.Collapse>
<Nav className="me-auto">
<Nav className="me-auto">
<Nav.Link href="/garage">Garage</Nav.Link>
</Nav>
</Navbar.Collapse>
Expand All @@ -58,4 +60,4 @@ function NavBar() {
);
}

export default NavBar;
export default NavBar;
10 changes: 9 additions & 1 deletion frontend/src/pages/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ import React, { useState } from 'react';
import Button from 'react-bootstrap/Button';
import Offcanvas from 'react-bootstrap/Offcanvas';
import {Nav} from "react-bootstrap";
import { useNavigate } from 'react-router-dom';

export const Settings = (props) => {
const [darkMode, setDarkMode] = useState(false);
const [notifications, setNotifications] = useState(false);
const [unitOfMeasurement, setUnitOfMeasurement] = useState('metric');

const navigate = useNavigate();
const [show, setShow] = useState(false);
const handleShow = () => setShow(!show);

const handleSubmit = (e) => {
e.preventDefault();
}

const handleLogout = () => {
localStorage.clear();
navigate('/');
window.location.reload();
}

return (
<div>
{/*<Button variant="primary" onClick={handleShow}>Settings</Button>*/}
Expand Down Expand Up @@ -45,7 +53,7 @@ export const Settings = (props) => {
</select>
</div>
<div className={"mt-3"}>
<Button variant="primary" onClick={() => localStorage.clear()}>Logout</Button>
<Button variant="primary" onClick={handleLogout}>Logout</Button>
</div>
</Offcanvas.Body>
</Offcanvas>
Expand Down
65 changes: 46 additions & 19 deletions frontend/src/pages/garage/AddVehicle.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import React, { useEffect, useState } from "react";
import { Button, Form, Container, Row, Col } from 'react-bootstrap';
import '../../App.css';
import {useNavigate} from "react-router-dom";

function AddVehicle() {

const EMAIL = process.env.EMAIL;
const [refreshData, setRefreshData] = useState(false);

const [vehicleAdded, setVehicleAdded] = useState(false);
const [configId, setConfigId] = useState(null);
const [dropdownValues, setDropdownValues] = useState({
Expand Down Expand Up @@ -50,34 +53,43 @@ function AddVehicle() {
}
};
fetchUser();
}, []);
}, [refreshData]);

useEffect(() => {
getDropdownValues('years');
}, []);

const handleChange = async (e) => {
const { name, value } = e.target;
const {name, value} = e.target;
setSelectedVehicle(prevSelectedVehicle => ({
...prevSelectedVehicle,
[name]: value
}));

if (name === 'year') {
getDropdownValues('makes', value);
setDropdownValues(prev => ({ ...prev, models: [], engines: [], transmissions: [] }));
setDropdownValues(prev => ({...prev, models: [], engines: [], transmissions: []}));
} else if (name === 'make') {
getDropdownValues('models', selectedVehicle.year, value);
setDropdownValues(prev => ({ ...prev, engines: [], transmissions: [] }));
setDropdownValues(prev => ({...prev, engines: [], transmissions: []}));
} else if (name === 'model') {
getDropdownValues('engines', selectedVehicle.year, selectedVehicle.make, value);
setDropdownValues(prev => ({ ...prev, transmissions: [] }));
setDropdownValues(prev => ({...prev, transmissions: []}));
} else if (name === 'engine') {
getDropdownValues('transmissions', selectedVehicle.year, selectedVehicle.make, selectedVehicle.model, value);
}
};

const getDropdownValues = async (category, year = '', make = '', model = '', engine = '') => {
const myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer " + localStorage.getItem('token'));
myHeaders.append("Content-Type", "application/json");

const reqOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
}
let url = `/api/get-${category}?`;
const params = new URLSearchParams();

Expand All @@ -89,7 +101,7 @@ function AddVehicle() {
url += params.toString();

try {
const response = await fetch(url);
const response = await fetch(url, reqOptions);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
Expand All @@ -110,9 +122,19 @@ function AddVehicle() {
};

const handleSelectAndAddVehicle = async () => {

const myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer " + localStorage.getItem('token'));
myHeaders.append("Content-Type", "application/json");

const reqOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
}
const queryParameters = new URLSearchParams(selectedVehicle).toString();
try {
const response = await fetch(`/api/get-config-id?${queryParameters}`);
const response = await fetch(`/api/get-config-id?${queryParameters}`, reqOptions);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
Expand All @@ -133,10 +155,11 @@ function AddVehicle() {
const response = await fetch('/api/add-vehicle', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + localStorage.getItem('token')
},
body: JSON.stringify({
email: "[email protected]", // Replace with dynamic user email
email: EMAIL,
config_id: configId
})
});
Expand All @@ -153,15 +176,16 @@ function AddVehicle() {
<Container className="mt-5">
<Row className="justify-content-md-center">
<h2>
<span onClick={() => navigate('/garage')} style={{ cursor: 'pointer', color: '#644A77', fontWeight: 'bold' }}>
<span onClick={() => navigate('/garage')}
style={{cursor: 'pointer', color: '#644A77', fontWeight: 'bold'}}>
{user} Garage
</span>
<span style={{ color: '#644A77', fontWeight: 'normal' }}> > Add New Vehicle</span>
<span style={{color: '#644A77', fontWeight: 'normal'}}> > Add New Vehicle</span>
</h2>
<Col md={6}>
<Form>
<Form.Group controlId="yearSelect">
<Form.Label style={{ fontWeight: 'bold', color: '#644A77' }}>Year</Form.Label>
<Form.Label style={{fontWeight: 'bold', color: '#644A77'}}>Year</Form.Label>
<Form.Select name="year" value={selectedVehicle.year} onChange={handleChange}>
<option value="">Select Year</option>
{dropdownValues.years.map((year, index) => (
Expand All @@ -172,7 +196,7 @@ function AddVehicle() {

{selectedVehicle.year && (
<Form.Group controlId="makeSelect">
<Form.Label style={{ fontWeight: 'bold', color: '#644A77' }}>Make</Form.Label>
<Form.Label style={{fontWeight: 'bold', color: '#644A77'}}>Make</Form.Label>
<Form.Select name="make" value={selectedVehicle.make} onChange={handleChange}>
<option value="">Select Make</option>
{dropdownValues.makes.map((make, index) => (
Expand All @@ -184,7 +208,7 @@ function AddVehicle() {

{selectedVehicle.make && (
<Form.Group controlId="modelSelect">
<Form.Label style={{ fontWeight: 'bold', color: '#644A77' }}>Model</Form.Label>
<Form.Label style={{fontWeight: 'bold', color: '#644A77'}}>Model</Form.Label>
<Form.Select name="model" value={selectedVehicle.model} onChange={handleChange}>
<option value="">Select Model</option>
{dropdownValues.models.map((model, index) => (
Expand All @@ -196,7 +220,7 @@ function AddVehicle() {

{selectedVehicle.model && (
<Form.Group controlId="engineSelect">
<Form.Label style={{ fontWeight: 'bold', color: '#644A77' }}>Engine</Form.Label>
<Form.Label style={{fontWeight: 'bold', color: '#644A77'}}>Engine</Form.Label>
<Form.Select name="engine" value={selectedVehicle.engine} onChange={handleChange}>
<option value="">Select Engine</option>
{dropdownValues.engines.map((engine, index) => (
Expand All @@ -208,8 +232,9 @@ function AddVehicle() {

{selectedVehicle.engine && (
<Form.Group controlId="transmissionSelect">
<Form.Label style={{ fontWeight: 'bold', color: '#644A77' }}>Transmission</Form.Label>
<Form.Select name="transmission" value={selectedVehicle.transmission} onChange={handleChange}>
<Form.Label style={{fontWeight: 'bold', color: '#644A77'}}>Transmission</Form.Label>
<Form.Select name="transmission" value={selectedVehicle.transmission}
onChange={handleChange}>
<option value="">Select Transmission</option>
{dropdownValues.transmissions.map((transmission, index) => (
<option key={index} value={transmission}>{transmission}</option>
Expand All @@ -219,7 +244,9 @@ function AddVehicle() {
)}

<div className="text-center mt-4">
<Button className="btn btn-primary" onClick={handleSelectAndAddVehicle} disabled={!selectedVehicle.transmission || vehicleAdded}>Select and Add Vehicle</Button>
<Button className="btn btn-primary" onClick={handleSelectAndAddVehicle}
disabled={!selectedVehicle.transmission || vehicleAdded}>Select and Add
Vehicle</Button>
</div>
{vehicleAdded && <div className="alert alert-success mt-4" role="alert">
Vehicle has been added successfully!
Expand Down
29 changes: 4 additions & 25 deletions frontend/src/pages/garage/Garage.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ function Garage(props) {
}, []);

useEffect(() => {

const myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer " + localStorage.getItem('token'));

const reqOptions = {
method: 'GET',
headers: myHeaders,
Expand All @@ -55,37 +58,13 @@ function Garage(props) {
.then(vehicles => {
props.setInfo(vehicles);
setLoading(false);
setRefreshData(false)
})
.catch(error => {
console.error('There has been a problem with your fetch operation:', error);
});
}, [refreshData]);

const updateOdometer = async (configID, email) => {
try{
const response = await fetch("/api/update-odometer", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
vehicle_config_ids : configID,
email: email,
//odometer: odometer
})
});
if(response.ok){
setRefreshData(!refreshData);
}
else{
console.error("Failed to update Odometer");
}
}
catch (error){
console.error("Catch Failed to update Odometer");
}
}

let vehicle_count = 0;

return (
Expand Down
Loading

0 comments on commit 9402bcb

Please sign in to comment.