Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion webapp_frontend/src/background/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {constants} from "../constants";

export const hostname:string =constants.url.API_URL+'/api';

export const userPath:string='/v1/users';


interface BackendHealthData {
uptimeInSeconds: number;
Expand All @@ -21,4 +23,4 @@ function callBackendHealth():Promise<BackendHealthData>{
});
}

export { callBackendHealth}
export { callBackendHealth}
76 changes: 76 additions & 0 deletions webapp_frontend/src/background/api/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import Axios from "axios";


import {hostname, userPath} from "./api";

import {AddUser, UserState} from "../redux/actions/userTypes";
import store from "../redux/store";
import {addAccessToken, addRefreshToken} from "../redux/actions/tokens";
import {addUser} from "../redux/actions/user";
import {AccessToken, AddAccessToken, AddRefreshToken, TokensState} from "../redux/actions/tokenTypes";


// reference: https://daveceddia.com/access-redux-store-outside-react/

export interface BackendLoginData {
refreshToken: string,
user: UserState

}

export const loginWithUsernameAndPassword = (userName: string, password: string): Promise<BackendLoginData> => {

return new Promise<BackendLoginData>((resolve, reject) => {
let config = {
headers: {
Authorization: `Basic ${btoa(userName + ':' + password)}`,
},
};

return Axios.get(hostname + userPath + '/login', config)
.then((data) => {
store.dispatch(addRefreshToken(data.data.refreshToken) as AddRefreshToken)
store.dispatch(addUser(data.data.user as UserState) as AddUser)

getAccessTokenWithRefreshToken()
})
.catch(((error) => {

reject(error);
}))


})
}


export const getAccessTokenWithRefreshToken = () => {
console.log("getAccessTokenWithRefreshToken")

let refreshToken: string|null = (store.getState().tokens as TokensState).refreshToken;

let config = {
headers: {
Authorization: `Bearer ${refreshToken}`,
},
};

Axios.get(hostname + userPath + '/auth', config)
.then((data) => {
setAuthHeaderToAxios(data.data.token)

store.dispatch(addAccessToken({token: data.data.token, timestamp: data.data.validUntil}as AccessToken) as AddAccessToken);

})
.catch(((error) => {
console.log(error)
}));

}

function setAuthHeaderToAxios(accessToken: string) {
Axios.defaults.headers.common['Authorization'] =
`Bearer ${accessToken}`;
}


7 changes: 0 additions & 7 deletions webapp_frontend/src/background/api/login.ts

This file was deleted.

4 changes: 2 additions & 2 deletions webapp_frontend/src/background/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const prod: constants = {

const dev: constants = {
url: {
API_URL: 'http://filefighter.ddns.net:3001',
API_URL: 'https://cors-anywhere.herokuapp.com/http://filefighter.ddns.net:3001',
}
};
export const constants = process.env.NODE_ENV === 'development' ? dev : prod;
export const constants = process.env.NODE_ENV === 'development' ? dev : prod;
4 changes: 3 additions & 1 deletion webapp_frontend/src/background/redux/actions/sytemState.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {TokensState} from "./tokenTypes";
import {UserState} from "./userTypes";

export interface SystemState {
tokens: TokensState
}
user: UserState
}
15 changes: 11 additions & 4 deletions webapp_frontend/src/background/redux/actions/tokenTypes.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export const ADD_REFRESH_TOKEN = "ADD_REFRESH_TOKEN";
export const ADD_ACCESS_TOKEN = "ADD_ACCESS_TOKEN";
export const CHECKED_COOKIES = "CHECKED_COOKIES";


export interface AccessToken{
export interface AccessToken {
token: string | null;
timestamp: number | null;
}
Expand All @@ -11,18 +12,24 @@ export interface AccessToken{
export interface TokensState {
refreshToken: string | null;
accessToken: AccessToken | null;
checkedCookies: boolean;
}


interface AddRefreshToken {
export interface AddRefreshToken {
type: typeof ADD_REFRESH_TOKEN
payload: string
}

interface AddAccessToken {
export interface AddAccessToken {
type: typeof ADD_ACCESS_TOKEN
payload: AccessToken
}

export type TokenActionsTypes = AddRefreshToken | AddAccessToken;
export interface CheckedCookies{
type: typeof CHECKED_COOKIES,
payload: boolean
}

export type TokenActionsTypes = AddRefreshToken | AddAccessToken|CheckedCookies;

10 changes: 8 additions & 2 deletions webapp_frontend/src/background/redux/actions/tokens.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ADD_REFRESH_TOKEN, ADD_ACCESS_TOKEN, AccessToken} from "./tokenTypes";
import {ADD_REFRESH_TOKEN, ADD_ACCESS_TOKEN, AccessToken, CHECKED_COOKIES} from "./tokenTypes";


export const addRefreshToken = (content: string) => ({
Expand All @@ -9,4 +9,10 @@ export const addRefreshToken = (content: string) => ({
export const addAccessToken = (content: AccessToken) => ({
type: ADD_ACCESS_TOKEN,
payload: content
});
});


export const checkedCookies = (content: boolean) => ({
type: CHECKED_COOKIES,
payload: content
});
6 changes: 6 additions & 0 deletions webapp_frontend/src/background/redux/actions/user.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {ADD_USER, UserState} from "./userTypes";

export const addUser = (content: UserState) => ({
type: ADD_USER,
payload: content
});
18 changes: 18 additions & 0 deletions webapp_frontend/src/background/redux/actions/userTypes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const ADD_USER = "ADD_USER";

export interface UserState {
id: number | null,
username: string | null,
groups: number[],


}


export interface AddUser {
type: typeof ADD_USER,
payload: UserState
}


export type UserActionTypes = AddUser;
4 changes: 3 additions & 1 deletion webapp_frontend/src/background/redux/reducers/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {combineReducers} from "redux";
import tokens from "./tokens";
import user from "./user";

// this combines all the stores from the reducers
export default combineReducers({tokens});

export default combineReducers({tokens, user});
20 changes: 16 additions & 4 deletions webapp_frontend/src/background/redux/reducers/tokens.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import {ADD_REFRESH_TOKEN, ADD_ACCESS_TOKEN, TokenActionsTypes, TokensState, AccessToken} from "../actions/tokenTypes";
import {ADD_REFRESH_TOKEN, ADD_ACCESS_TOKEN, TokenActionsTypes, TokensState, AccessToken, CHECKED_COOKIES} from "../actions/tokenTypes";

const initialState: TokensState = {
refreshToken: null,
accessToken: null,
checkedCookies: false,
};

export default function (state = initialState, action: TokenActionsTypes) {
switch (action.type) {
case ADD_REFRESH_TOKEN: {
console.log('[Redux] adding refreshToken')
const refreshToken: string = action.payload;
return {
refreshToken: refreshToken,
accessToken: initialState.accessToken
accessToken: state.accessToken,
checkedCookies: state.checkedCookies
};
}
case ADD_ACCESS_TOKEN: {
console.log('[Redux] adding accessToken')
const accessToken: AccessToken = action.payload;
return {
refreshToken: initialState.refreshToken,
accessToken: accessToken
refreshToken: state.refreshToken,
accessToken: accessToken,
checkedCookies: state.checkedCookies
};
}
case CHECKED_COOKIES: {
return {
refreshToken: state.refreshToken,
accessToken: state.refreshToken,
checkedCookies: action.payload
};
}
default:
Expand Down
18 changes: 18 additions & 0 deletions webapp_frontend/src/background/redux/reducers/user.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {ADD_USER, UserActionTypes, UserState} from "../actions/userTypes";

const initialState: UserState = {
groups: [], id: null, username: null

};


export default function (state = initialState, action: UserActionTypes) {
switch (action.type) {
case ADD_USER: {
console.log('[Redux] adding user')
return action.payload;
}
default:
return state;
}
}
47 changes: 32 additions & 15 deletions webapp_frontend/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@ import PermanentAssets from "./basicElements/PermanentAssets";


import {connect, ConnectedProps} from 'react-redux'
import {addAccessToken, addRefreshToken} from "../background/redux/actions/tokens";
import {addAccessToken, addRefreshToken, checkedCookies} from "../background/redux/actions/tokens";
import {SystemState} from "../background/redux/actions/sytemState";

import Login from "./basicElements/Login";



// this takes the redux store and maps everything that is needed to the function props
const mapState = (state: SystemState) => ({
tokens: {refreshToken: state.tokens.refreshToken, accessToken: state.tokens.accessToken}
tokens: {refreshToken: state.tokens.refreshToken, accessToken: state.tokens.accessToken, checkedCookies: state.tokens.checkedCookies},
user: state.user
})

// this takes the redux actions and maps them to the props
const mapDispatch = {
addRefreshToken, addAccessToken
addRefreshToken, addAccessToken, checkedCookies
}

const connector = connect(mapState, mapDispatch)
Expand All @@ -36,20 +40,33 @@ function App(props: Props): ReactElement {
console.log("[App] props.tokens: ")
console.log(props.tokens.refreshToken)
console.log(props.tokens)
console.log(props.user)

if (props.tokens.checkedCookies) {

if (props.tokens.refreshToken) {

return (
<div className="App">
<BrowserRouter>
<Header/>
<Container>
<Router/>
</Container>
<Footer/>
<PermanentAssets/>
</BrowserRouter>
</div>
);
} else {
console.log("[APP] showing login");
return (<Login/>)
}
} else {
props.checkedCookies(true)

return (
<div className="App">
<BrowserRouter>
<Header/>
<Container>
<Router/>
</Container>
<Footer/>
<PermanentAssets/>
</BrowserRouter>
</div>
);
return (<div>Loading</div>)
}
}

export default connector(App);
Loading