to do: troubleshoot missing token in request headers

This commit is contained in:
Mikayla Dobson
2023-02-11 21:51:39 -06:00
parent 90a5bdf128
commit 1b73fa6b99
13 changed files with 109 additions and 114 deletions

View File

@@ -3,6 +3,7 @@ import { useEffect } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { useAuthContext } from './context/AuthContext';
import jwtDecode from 'jwt-decode';
import API from './util/API';
// pages, ui, components, styles
import Subscriptions from './components/pages/Subscriptions/Subscriptions';
@@ -22,7 +23,7 @@ import { TokenType } from './util/types';
import './sass/App.scss';
function App() {
const { setUser, setToken } = useAuthContext();
const { setUser, token, setToken } = useAuthContext();
useEffect(() => {
if (document.cookie) {
@@ -30,7 +31,11 @@ function App() {
setToken(document.cookie.split("=")[1]);
setUser(extractedToken.user);
}
}, []);
}, [document.cookie]);
useEffect(() => {
token && API.Settings.setToken(token);
}, [token])
return (
<BrowserRouter>

View File

@@ -10,7 +10,7 @@ const AddRecipe = () => {
const getFormState = useCallback((data: IRecipe) => {
setInput(data);
}, [])
}, [input])
const handleCreate = () => {
for (let field of Object.keys(input)) {
@@ -28,20 +28,6 @@ const AddRecipe = () => {
}
})
}, [authContext])
useEffect(() => {
input.authoruserid && setForm(
new Form<IRecipe>({
parent: "AddRecipe",
keys: ["name", "preptime", "course", "cuisine", "ingredients", "description"],
labels: ["Recipe Name:", "Prep Time:", "Course:", "Cuisine:", "Ingredients:", "Description:"],
dataTypes: ['text', 'text', 'custom picker', 'custom picker', 'custom picker', 'TINYMCE'],
initialState: input,
getState: getFormState,
richTextInitialValue: "<p>Enter recipe details here!</p>"
}).mount()
)
}, [input.authoruserid])
useEffect(() => {
console.log(input);
@@ -53,7 +39,18 @@ const AddRecipe = () => {
<Divider />
<Panel>
<Form parent={input} _config={{
parent: "AddRecipe",
keys: ["name", "preptime", "course", "cuisine", "ingredients", "description"],
labels: ["Recipe Name:", "Prep Time:", "Course:", "Cuisine:", "Ingredients:", "Description:"],
dataTypes: ['text', 'text', 'custom picker', 'custom picker', 'custom picker', 'TINYMCE'],
initialState: input,
getState: getFormState,
richTextInitialValue: "<p>Enter recipe details here!</p>"
}} />
{ form || <h2>Loading...</h2> }
<Button onClick={handleCreate}>Create Recipe!</Button>
</Panel>
</Page>

View File

@@ -9,8 +9,7 @@ import API from "../../util/API";
export default function Login() {
const params = new URLSearchParams(window.location.search);
const redirect = params.get("redirect");
const { user, setUser } = useContext(AuthContext);
const [form, setForm] = useState<JSX.Element>();
const { user, setToken } = useContext(AuthContext);
// setup and local state
const navigate = useNavigate();
@@ -25,11 +24,12 @@ export default function Login() {
const handleLogin = async () => {
if (!input.email || !input.password) return;
const result = await new API.Auth().login(input);
console.log(result);
// const { data, ok } = await attemptLogin(input);
// if (ok) setUser(data);
// navigate(`/${redirect ?? ''}`);
// setting token will trigger ui update
setToken(result.token);
// if there is a redirect, go there, else go home
navigate(`/${redirect ?? ''}`);
}
// check for logged in user and mount form
@@ -37,10 +37,6 @@ export default function Login() {
if (user) navigate('/');
}, [])
useEffect(() => {
console.log(input);
}, [getFormState])
return (
<Page>
<h1>Hello! Nice to see you again.</h1>
@@ -54,7 +50,7 @@ export default function Login() {
dataTypes: Object.keys(input),
initialState: input,
getState: getFormState
} as FormConfig<typeof input>} />
}} />
<Button onClick={handleLogin}>Log In</Button>

View File

@@ -14,8 +14,7 @@ export default function Profile() {
return (
<Protect redirect="profile">
<div className="profile-authenticated">
<h1>{user?.firstname}'s Profile</h1>
<p>Things and stuff!</p>
<h1>{user && user.firstname}'s Profile</h1>
<Friends />
</div>
</Protect>

View File

@@ -5,9 +5,10 @@ import { RegisterVariantType, VariantLabel } from ".";
import { useAuthContext } from "../../../context/AuthContext";
import { IUser, IUserAuth } from "../../../schemas";
import { attemptLogin, attemptRegister } from "../../../util/apiUtils";
import API from "../../../util/API";
import { Button, Page, Panel } from "../../ui";
import Divider from "../../ui/Divider";
import Form, { FormConfig } from "../../ui/Form";
import Form from "../../ui/Form";
const blankUser: IUser = {
firstname: '',
@@ -20,51 +21,31 @@ const blankUser: IUser = {
}
const AboutYou: RegisterVariantType = ({ transitionDisplay }) => {
const auth = new API.Auth();
const navigate = useNavigate();
const authContext = useAuthContext();
const [form, setForm] = useState<JSX.Element>(<p key={v4()}>Loading content...</p>);
const { user, setToken } = useAuthContext();
const [input, setInput] = useState<IUser>(blankUser);
const [regSuccess, setRegSuccess] = useState<any>();
const getFormState = useCallback((received: IUser) => {
setInput(received);
}, []);
useEffect(() => {
if (authContext.user) navigate('/');
}, [authContext]);
if (user) navigate('/');
}, [user]);
async function handleRegister() {
const res = await attemptRegister(input);
const res = await auth.register(input);
if (res.ok) {
setTimeout(async () => {
const result = await auth.login(input);
setToken(result.token);
}, 750);
transitionDisplay(VariantLabel.InitialCollection, input);
}
}
async function unwrapLogin() {
const data: IUserAuth = { email: input.email, password: input.password || "" }
const login = await attemptLogin(data);
if (login) {
authContext.user = login.user;
}
navigate('/');
}
useEffect(() => {
setForm(new Form<IUser>({
parent: "register",
keys: ['firstname', 'lastname', 'handle', 'email', 'password'],
initialState: input,
labels: ['First Name', 'Last Name', 'Handle', 'Email', "Password"],
dataTypes: ['text', 'text', 'text', 'email', 'password'],
getState: getFormState
}).mount());
}, [])
useEffect(() => {
if (regSuccess) unwrapLogin();
}, [regSuccess])
return (
<Page>
<h1>Hi! Thanks for being here.</h1>
@@ -74,7 +55,16 @@ const AboutYou: RegisterVariantType = ({ transitionDisplay }) => {
<h2>Tell us a bit about yourself:</h2>
<Panel extraStyles="form-panel two-columns">
{ form || <h2>Loading...</h2> }
<Form parent={input} _config={{
parent: "register",
keys: ['firstname', 'lastname', 'handle', 'email', 'password'],
initialState: input,
labels: ['First Name', 'Last Name', 'Handle', 'Email', "Password"],
dataTypes: ['text', 'text', 'text', 'email', 'password'],
getState: getFormState
}} />
<Button onClick={handleRegister}>Register</Button>
</Panel>
</Page>

View File

@@ -3,33 +3,23 @@ import { RegisterVariantType, VariantLabel } from ".";
import { useNow } from "../../../hooks/useNow";
import { ICollection, IUser, IUserAuth } from "../../../schemas";
import { attemptLogin, createNewCollection } from "../../../util/apiUtils";
import API from "../../../util/API";
import { Button, Divider, Page, Panel } from "../../ui";
import TextField from "../../ui/TextField";
import { useAuthContext } from "../../../context/AuthContext";
const InitialCollection: RegisterVariantType = ({ transitionDisplay, input }) => {
const { user, setUser } = useAuthContext();
const [collectionName, setCollectionName] = useState<string>();
const [view, setView] = useState<JSX.Element>(<Page><h1>Loading...</h1></Page>);
const [user, setUser] = useState<IUser>();
const now = useNow();
async function unwrapLogin(data: IUser) {
const userInfo: IUserAuth = { email: data.email, password: data.password! }
const login = await attemptLogin(userInfo);
setUser(login.user);
}
useEffect(() => {
if (input) {
setTimeout(() => {
unwrapLogin(input);
}, 750);
}
}, [])
const collectionAPI = new API.Collection();
const handleClick = async () => {
if (!user) return;
const collection: ICollection = {
name: collectionName || (user.firstname + "'s Collection"),
name: collectionName ?? (user.firstname + "'s Collection"),
active: true,
ismaincollection: true,
ownerid: user.id!.toString(),
@@ -39,7 +29,7 @@ const InitialCollection: RegisterVariantType = ({ transitionDisplay, input }) =>
console.log(collection);
const result = await createNewCollection(collection);
const result = await collectionAPI.post(collection);
console.log(result);
if (result) transitionDisplay(VariantLabel.AddFriends);
}
@@ -58,7 +48,8 @@ const InitialCollection: RegisterVariantType = ({ transitionDisplay, input }) =>
<Divider />
<h3>What would you like to call your main collection?</h3>
<TextField onChange={(e: ChangeEvent<HTMLInputElement>) => setCollectionName(e.target.value)} placeholder={user.firstname + 's Collection'} />
{/* <TextField onChange={(e: ChangeEvent<HTMLInputElement>) => setCollectionName(e.target.value)} placeholder={user.firstname + 's Collection'} /> */}
<input type="text" onChange={(e) => setCollectionName(e.target.value)} placeholder={user.firstname + 's Collection'}></input>
</Panel>
<Button onClick={handleClick}>Next</Button>

View File

@@ -1,7 +1,7 @@
import API from "../../../util/API";
import { NavbarType } from "../../../util/types";
import { Button, Dropdown } from '..'
import { useState } from "react";
import { useEffect, useState } from "react";
import { useAuthContext } from "../../../context/AuthContext";
import { useNavigate } from "react-router-dom";
@@ -40,6 +40,10 @@ const LoggedIn = () => {
navigate(payload);
}
useEffect(() => {
console.log(user);
}, [])
return (
<div>
<div id="navbar">
@@ -47,7 +51,7 @@ const LoggedIn = () => {
<a onClick={() => navigate('/')}>RECIPIN</a>
</div>
<div className="navbar-block">
<p>Hi, {user?.firstname}.</p>
<p>Hi, {user && user.firstname}.</p>
<span id="search-icon"></span>
<Button onClick={() => handleUIChange("SEARCH")}>Search</Button>
<Button onClick={() => handleUIChange("ACTIONS")}>Actions</Button>

View File

@@ -3,12 +3,15 @@ import { IUser } from "../../../schemas";
import { TextField, UserCard } from "..";
import { v4 } from "uuid";
import { getAllUsers } from "../../../util/apiUtils";
import API from "../../../util/API";
const FriendSearchWidget: FC<{}> = () => {
const [searchTerm, setSearchTerm] = useState<string>();
const [userPool, setUserPool] = useState<IUser[]>([]);
const [friendResults, setFriendResults] = useState<IUser[]>([]);
const users = new API.User();
// this isn't really working right now i don't think
const handleRequestSent = useCallback((targetid: string | number) => {
setUserPool((prev: IUser[]) => {
@@ -23,7 +26,7 @@ const FriendSearchWidget: FC<{}> = () => {
// load available user pool on mount
useEffect(() => {
(async function() {
const result = await getAllUsers();
const result = await users.getAll();
if (result) setUserPool(result);
})();
}, [])

View File

@@ -3,57 +3,61 @@ import { IUser, IUserAuth, IFriendship, IRecipe, IIngredient, ICollection, IGroc
import { default as _instance } from "./axiosInstance";
module API {
const APISTRING = import.meta.env.APISTRING || "http://localhost:8080";
export class Settings {
private static APISTRING = import.meta.env.APISTRING || "http://localhost:8080";
private static token?: string;
public static getAPISTRING() {
return Settings.APISTRING;
}
public static getToken() {
return Settings.token;
}
public static setToken(newToken: string) {
Settings.token = newToken;
}
}
abstract class RestController<T> {
protected instance = _instance;
protected endpoint: string;
protected token?: string;
protected headers?: any
constructor(endpoint: string, token?: string) {
constructor(endpoint: string) {
this.endpoint = endpoint;
this.token = token;
if (token) {
if (Settings.getToken()) {
this.headers = {
"Content-Type": "application/json",
"Authorization": ("Bearer " + token)
"Authorization": ("Bearer " + Settings.getToken())
};
}
}
async getAll() {
if (!this.token) return null;
const response = await this.instance.get(this.endpoint, this.headers);
return Promise.resolve(response.data);
}
async getByID(id: string) {
if (!this.token) return null;
const response = await this.instance.get(this.endpoint + "/" + id, this.headers);
return Promise.resolve(response.data);
}
async postOne(data: T) {
if (!this.token) return null;
async post(data: T) {
console.log(data);
const response = await this.instance.post(this.endpoint, data, this.headers);
return Promise.resolve(response.data);
}
async put(id: string, data: T | Partial<T>) {
if (!this.token) return null;
const response = await this.instance.put(this.endpoint + "/" + id, data, this.headers);
const response = await this.instance.put(this.endpoint + "/" + id, JSON.stringify(data), this.headers);
return Promise.resolve(response.data);
}
async delete(id: string) {
if (!this.token) return null;
const response = await this.instance.delete(this.endpoint + '/' + id, this.headers);
return Promise.resolve(response.data);
}
@@ -61,7 +65,7 @@ module API {
export class Auth {
private instance = _instance;
private endpoint = APISTRING + "/auth";
private endpoint = Settings.getAPISTRING() + "/auth";
async login(data: IUserAuth | Partial<IUser>) {
try {
@@ -109,18 +113,16 @@ module API {
export class User extends RestController<IUser> {
constructor() {
super(APISTRING + "/app/users");
super(Settings.getAPISTRING() + "/app/users");
}
}
export class Friendship extends RestController<IFriendship> {
constructor() {
super(APISTRING + "/app/friends");
super(Settings.getAPISTRING() + "/app/friends");
}
async getPendingFriendRequests() {
if (!this.token) return null;
const response = await this.instance.get(this.endpoint + "?pending=true", this.headers);
return Promise.resolve(response.data);
}
@@ -128,25 +130,25 @@ module API {
export class Recipe extends RestController<IRecipe> {
constructor() {
super(APISTRING + "/app/recipes");
super(Settings.getAPISTRING() + "/app/recipes");
}
}
export class Ingredient extends RestController<IIngredient> {
constructor() {
super(APISTRING + "/app/ingredients");
super(Settings.getAPISTRING() + "/app/ingredients");
}
}
export class Collection extends RestController<ICollection> {
constructor() {
super(APISTRING + "/app/collections");
super(Settings.getAPISTRING() + "/app/collection");
}
}
export class GroceryList extends RestController<IGroceryList> {
constructor() {
super(APISTRING + "/app/grocery-list")
super(Settings.getAPISTRING() + "/app/grocery-list")
}
}
}