Added auth headers to api requests

This commit is contained in:
Paweł Malak 2021-11-12 12:38:01 +01:00
parent 0d36c5cf94
commit d94a6cea5a
12 changed files with 135 additions and 56 deletions

View file

@ -29,7 +29,10 @@ interface Props {
} }
export const Apps = (props: Props): JSX.Element => { export const Apps = (props: Props): JSX.Element => {
const { apps, loading } = useSelector((state: State) => state.apps); const {
apps: { apps, loading },
auth: { isAuthenticated },
} = useSelector((state: State) => state);
const dispatch = useDispatch(); const dispatch = useDispatch();
const { getApps } = bindActionCreators(actionCreators, dispatch); const { getApps } = bindActionCreators(actionCreators, dispatch);
@ -76,10 +79,12 @@ export const Apps = (props: Props): JSX.Element => {
subtitle={<Link to="/">Go back</Link>} subtitle={<Link to="/">Go back</Link>}
/> />
<div className={classes.ActionsContainer}> {isAuthenticated && (
<ActionButton name="Add" icon="mdiPlusBox" handler={toggleModal} /> <div className={classes.ActionsContainer}>
<ActionButton name="Edit" icon="mdiPencil" handler={toggleEdit} /> <ActionButton name="Add" icon="mdiPlusBox" handler={toggleModal} />
</div> <ActionButton name="Edit" icon="mdiPencil" handler={toggleEdit} />
</div>
)}
<div className={classes.Apps}> <div className={classes.Apps}>
{loading ? ( {loading ? (

View file

@ -34,9 +34,10 @@ export enum ContentType {
} }
export const Bookmarks = (props: Props): JSX.Element => { export const Bookmarks = (props: Props): JSX.Element => {
const { loading, categories } = useSelector( const {
(state: State) => state.bookmarks bookmarks: { loading, categories },
); auth: { isAuthenticated },
} = useSelector((state: State) => state);
const dispatch = useDispatch(); const dispatch = useDispatch();
const { getCategories } = bindActionCreators(actionCreators, dispatch); const { getCategories } = bindActionCreators(actionCreators, dispatch);
@ -109,28 +110,30 @@ export const Bookmarks = (props: Props): JSX.Element => {
<Headline title="All Bookmarks" subtitle={<Link to="/">Go back</Link>} /> <Headline title="All Bookmarks" subtitle={<Link to="/">Go back</Link>} />
<div className={classes.ActionsContainer}> {isAuthenticated && (
<ActionButton <div className={classes.ActionsContainer}>
name="Add Category" <ActionButton
icon="mdiPlusBox" name="Add Category"
handler={() => addActionHandler(ContentType.category)} icon="mdiPlusBox"
/> handler={() => addActionHandler(ContentType.category)}
<ActionButton />
name="Add Bookmark" <ActionButton
icon="mdiPlusBox" name="Add Bookmark"
handler={() => addActionHandler(ContentType.bookmark)} icon="mdiPlusBox"
/> handler={() => addActionHandler(ContentType.bookmark)}
<ActionButton />
name="Edit Categories" <ActionButton
icon="mdiPencil" name="Edit Categories"
handler={() => editActionHandler(ContentType.category)} icon="mdiPencil"
/> handler={() => editActionHandler(ContentType.category)}
<ActionButton />
name="Edit Bookmarks" <ActionButton
icon="mdiPencil" name="Edit Bookmarks"
handler={() => editActionHandler(ContentType.bookmark)} icon="mdiPencil"
/> handler={() => editActionHandler(ContentType.bookmark)}
</div> />
</div>
)}
{loading ? ( {loading ? (
<Spinner /> <Spinner />

View file

@ -124,7 +124,9 @@ export const Home = (): JSX.Element => {
<BookmarkGrid <BookmarkGrid
categories={ categories={
!bookmarkSearchResult !bookmarkSearchResult
? categories.filter(({ isPinned }) => isPinned) ? categories.filter(
({ isPinned, bookmarks }) => isPinned && bookmarks.length
)
: bookmarkSearchResult : bookmarkSearchResult
} }
totalCategories={categories.length} totalCategories={categories.length}

View file

@ -51,6 +51,7 @@ export const AuthForm = (): JSX.Element => {
id="password" id="password"
name="password" name="password"
placeholder="••••••" placeholder="••••••"
autoComplete="current-password"
value={formData.password} value={formData.password}
onChange={(e) => onChange={(e) =>
setFormData({ ...formData, password: e.target.value }) setFormData({ ...formData, password: e.target.value })

View file

@ -9,8 +9,9 @@ import { actionCreators } from '../../../store';
// Typescript // Typescript
import { ApiResponse } from '../../../interfaces'; import { ApiResponse } from '../../../interfaces';
// UI // Other
import { InputGroup, Button } from '../../UI'; import { InputGroup, Button } from '../../UI';
import { applyAuth } from '../../../utility';
export const StyleSettings = (): JSX.Element => { export const StyleSettings = (): JSX.Element => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -34,7 +35,11 @@ export const StyleSettings = (): JSX.Element => {
e.preventDefault(); e.preventDefault();
axios axios
.put<ApiResponse<{}>>('/api/config/0/css', { styles: customStyles }) .put<ApiResponse<{}>>(
'/api/config/0/css',
{ styles: customStyles },
{ headers: applyAuth() }
)
.then(() => { .then(() => {
createNotification({ createNotification({
title: 'Success', title: 'Success',

View file

@ -5,7 +5,7 @@ import axios from 'axios';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
// Typescript // Typescript
import { Weather, ApiResponse, Config } from '../../../interfaces'; import { Weather, ApiResponse } from '../../../interfaces';
// CSS // CSS
import classes from './WeatherWidget.module.css'; import classes from './WeatherWidget.module.css';

View file

@ -11,6 +11,7 @@ import {
UpdateAppAction, UpdateAppAction,
} from '../actions/app'; } from '../actions/app';
import axios from 'axios'; import axios from 'axios';
import { applyAuth } from '../../utility';
export const getApps = export const getApps =
() => async (dispatch: Dispatch<GetAppsAction<undefined | App[]>>) => { () => async (dispatch: Dispatch<GetAppsAction<undefined | App[]>>) => {
@ -20,7 +21,9 @@ export const getApps =
}); });
try { try {
const res = await axios.get<ApiResponse<App[]>>('/api/apps'); const res = await axios.get<ApiResponse<App[]>>('/api/apps', {
headers: applyAuth(),
});
dispatch({ dispatch({
type: ActionType.getAppsSuccess, type: ActionType.getAppsSuccess,
@ -35,9 +38,15 @@ export const pinApp =
(app: App) => async (dispatch: Dispatch<PinAppAction>) => { (app: App) => async (dispatch: Dispatch<PinAppAction>) => {
try { try {
const { id, isPinned, name } = app; const { id, isPinned, name } = app;
const res = await axios.put<ApiResponse<App>>(`/api/apps/${id}`, { const res = await axios.put<ApiResponse<App>>(
isPinned: !isPinned, `/api/apps/${id}`,
}); {
isPinned: !isPinned,
},
{
headers: applyAuth(),
}
);
const status = isPinned const status = isPinned
? 'unpinned from Homescreen' ? 'unpinned from Homescreen'
@ -63,7 +72,9 @@ export const pinApp =
export const addApp = export const addApp =
(formData: NewApp | FormData) => async (dispatch: Dispatch<AddAppAction>) => { (formData: NewApp | FormData) => async (dispatch: Dispatch<AddAppAction>) => {
try { try {
const res = await axios.post<ApiResponse<App>>('/api/apps', formData); const res = await axios.post<ApiResponse<App>>('/api/apps', formData, {
headers: applyAuth(),
});
dispatch<any>({ dispatch<any>({
type: ActionType.createNotification, type: ActionType.createNotification,
@ -88,7 +99,9 @@ export const addApp =
export const deleteApp = export const deleteApp =
(id: number) => async (dispatch: Dispatch<DeleteAppAction>) => { (id: number) => async (dispatch: Dispatch<DeleteAppAction>) => {
try { try {
await axios.delete<ApiResponse<{}>>(`/api/apps/${id}`); await axios.delete<ApiResponse<{}>>(`/api/apps/${id}`, {
headers: applyAuth(),
});
dispatch<any>({ dispatch<any>({
type: ActionType.createNotification, type: ActionType.createNotification,
@ -113,7 +126,10 @@ export const updateApp =
try { try {
const res = await axios.put<ApiResponse<App>>( const res = await axios.put<ApiResponse<App>>(
`/api/apps/${id}`, `/api/apps/${id}`,
formData formData,
{
headers: applyAuth(),
}
); );
dispatch<any>({ dispatch<any>({
@ -155,7 +171,9 @@ export const reorderApps =
}) })
); );
await axios.put<ApiResponse<{}>>('/api/apps/0/reorder', updateQuery); await axios.put<ApiResponse<{}>>('/api/apps/0/reorder', updateQuery, {
headers: applyAuth(),
});
dispatch({ dispatch({
type: ActionType.reorderApps, type: ActionType.reorderApps,

View file

@ -8,6 +8,7 @@ import {
LogoutAction, LogoutAction,
} from '../actions/auth'; } from '../actions/auth';
import axios, { AxiosError } from 'axios'; import axios, { AxiosError } from 'axios';
import { getApps, getCategories } from '.';
export const login = export const login =
(formData: { password: string; duration: string }) => (formData: { password: string; duration: string }) =>
@ -24,6 +25,9 @@ export const login =
type: ActionType.login, type: ActionType.login,
payload: res.data.data.token, payload: res.data.data.token,
}); });
dispatch<any>(getApps());
dispatch<any>(getCategories());
} catch (err) { } catch (err) {
dispatch<any>(authError(err, true)); dispatch<any>(authError(err, true));
} }
@ -35,6 +39,9 @@ export const logout = () => (dispatch: Dispatch<LogoutAction>) => {
dispatch({ dispatch({
type: ActionType.logout, type: ActionType.logout,
}); });
dispatch<any>(getApps());
dispatch<any>(getCategories());
}; };
export const autoLogin = () => async (dispatch: Dispatch<AutoLoginAction>) => { export const autoLogin = () => async (dispatch: Dispatch<AutoLoginAction>) => {
@ -50,6 +57,9 @@ export const autoLogin = () => async (dispatch: Dispatch<AutoLoginAction>) => {
type: ActionType.autoLogin, type: ActionType.autoLogin,
payload: token, payload: token,
}); });
dispatch<any>(getApps());
dispatch<any>(getCategories());
} catch (err) { } catch (err) {
dispatch<any>(authError(err, false)); dispatch<any>(authError(err, false));
} }
@ -69,4 +79,7 @@ export const authError =
}, },
}); });
} }
dispatch<any>(getApps());
dispatch<any>(getCategories());
}; };

View file

@ -8,6 +8,7 @@ import {
NewBookmark, NewBookmark,
NewCategory, NewCategory,
} from '../../interfaces'; } from '../../interfaces';
import { applyAuth } from '../../utility';
import { ActionType } from '../action-types'; import { ActionType } from '../action-types';
import { import {
AddBookmarkAction, AddBookmarkAction,
@ -31,7 +32,9 @@ export const getCategories =
}); });
try { try {
const res = await axios.get<ApiResponse<Category[]>>('/api/categories'); const res = await axios.get<ApiResponse<Category[]>>('/api/categories', {
headers: applyAuth(),
});
dispatch({ dispatch({
type: ActionType.getCategoriesSuccess, type: ActionType.getCategoriesSuccess,
@ -47,7 +50,8 @@ export const addCategory =
try { try {
const res = await axios.post<ApiResponse<Category>>( const res = await axios.post<ApiResponse<Category>>(
'/api/categories', '/api/categories',
formData formData,
{ headers: applyAuth() }
); );
dispatch<any>({ dispatch<any>({
@ -75,7 +79,8 @@ export const addBookmark =
try { try {
const res = await axios.post<ApiResponse<Bookmark>>( const res = await axios.post<ApiResponse<Bookmark>>(
'/api/bookmarks', '/api/bookmarks',
formData formData,
{ headers: applyAuth() }
); );
dispatch<any>({ dispatch<any>({
@ -101,7 +106,8 @@ export const pinCategory =
const { id, isPinned, name } = category; const { id, isPinned, name } = category;
const res = await axios.put<ApiResponse<Category>>( const res = await axios.put<ApiResponse<Category>>(
`/api/categories/${id}`, `/api/categories/${id}`,
{ isPinned: !isPinned } { isPinned: !isPinned },
{ headers: applyAuth() }
); );
const status = isPinned const status = isPinned
@ -128,7 +134,9 @@ export const pinCategory =
export const deleteCategory = export const deleteCategory =
(id: number) => async (dispatch: Dispatch<DeleteCategoryAction>) => { (id: number) => async (dispatch: Dispatch<DeleteCategoryAction>) => {
try { try {
await axios.delete<ApiResponse<{}>>(`/api/categories/${id}`); await axios.delete<ApiResponse<{}>>(`/api/categories/${id}`, {
headers: applyAuth(),
});
dispatch<any>({ dispatch<any>({
type: ActionType.createNotification, type: ActionType.createNotification,
@ -153,7 +161,8 @@ export const updateCategory =
try { try {
const res = await axios.put<ApiResponse<Category>>( const res = await axios.put<ApiResponse<Category>>(
`/api/categories/${id}`, `/api/categories/${id}`,
formData formData,
{ headers: applyAuth() }
); );
dispatch<any>({ dispatch<any>({
@ -179,7 +188,9 @@ export const deleteBookmark =
(bookmarkId: number, categoryId: number) => (bookmarkId: number, categoryId: number) =>
async (dispatch: Dispatch<DeleteBookmarkAction>) => { async (dispatch: Dispatch<DeleteBookmarkAction>) => {
try { try {
await axios.delete<ApiResponse<{}>>(`/api/bookmarks/${bookmarkId}`); await axios.delete<ApiResponse<{}>>(`/api/bookmarks/${bookmarkId}`, {
headers: applyAuth(),
});
dispatch<any>({ dispatch<any>({
type: ActionType.createNotification, type: ActionType.createNotification,
@ -218,7 +229,8 @@ export const updateBookmark =
try { try {
const res = await axios.put<ApiResponse<Bookmark>>( const res = await axios.put<ApiResponse<Bookmark>>(
`/api/bookmarks/${bookmarkId}`, `/api/bookmarks/${bookmarkId}`,
formData formData,
{ headers: applyAuth() }
); );
dispatch<any>({ dispatch<any>({
@ -295,7 +307,8 @@ export const reorderCategories =
await axios.put<ApiResponse<{}>>( await axios.put<ApiResponse<{}>>(
'/api/categories/0/reorder', '/api/categories/0/reorder',
updateQuery updateQuery,
{ headers: applyAuth() }
); );
dispatch({ dispatch({

View file

@ -18,7 +18,7 @@ import {
WeatherForm, WeatherForm,
} from '../../interfaces'; } from '../../interfaces';
import { ActionType } from '../action-types'; import { ActionType } from '../action-types';
import { storeUIConfig } from '../../utility'; import { storeUIConfig, applyAuth } from '../../utility';
const keys: (keyof Config)[] = [ const keys: (keyof Config)[] = [
'useAmericanDate', 'useAmericanDate',
@ -55,7 +55,13 @@ export const updateConfig =
) => ) =>
async (dispatch: Dispatch<UpdateConfigAction>) => { async (dispatch: Dispatch<UpdateConfigAction>) => {
try { try {
const res = await axios.put<ApiResponse<Config>>('/api/config', formData); const res = await axios.put<ApiResponse<Config>>(
'/api/config',
formData,
{
headers: applyAuth(),
}
);
dispatch<any>({ dispatch<any>({
type: ActionType.createNotification, type: ActionType.createNotification,
@ -96,7 +102,9 @@ export const fetchQueries =
export const addQuery = export const addQuery =
(query: Query) => async (dispatch: Dispatch<AddQueryAction>) => { (query: Query) => async (dispatch: Dispatch<AddQueryAction>) => {
try { try {
const res = await axios.post<ApiResponse<Query>>('/api/queries', query); const res = await axios.post<ApiResponse<Query>>('/api/queries', query, {
headers: applyAuth(),
});
dispatch({ dispatch({
type: ActionType.addQuery, type: ActionType.addQuery,
@ -111,7 +119,10 @@ export const deleteQuery =
(prefix: string) => async (dispatch: Dispatch<DeleteQueryAction>) => { (prefix: string) => async (dispatch: Dispatch<DeleteQueryAction>) => {
try { try {
const res = await axios.delete<ApiResponse<Query[]>>( const res = await axios.delete<ApiResponse<Query[]>>(
`/api/queries/${prefix}` `/api/queries/${prefix}`,
{
headers: applyAuth(),
}
); );
dispatch({ dispatch({
@ -129,7 +140,10 @@ export const updateQuery =
try { try {
const res = await axios.put<ApiResponse<Query[]>>( const res = await axios.put<ApiResponse<Query[]>>(
`/api/queries/${oldPrefix}`, `/api/queries/${oldPrefix}`,
query query,
{
headers: applyAuth(),
}
); );
dispatch({ dispatch({

View file

@ -0,0 +1,4 @@
export const applyAuth = () => {
const token = localStorage.getItem('token') || '';
return { Authorization: `Bearer ${token}` };
};

View file

@ -10,3 +10,4 @@ export * from './storeUIConfig';
export * from './validators'; export * from './validators';
export * from './parseTime'; export * from './parseTime';
export * from './decodeToken'; export * from './decodeToken';
export * from './applyAuth';