Skip to content
Snippets Groups Projects
Commit 121be847 authored by Albin Henriksson's avatar Albin Henriksson
Browse files

Use secure route for competition

parent 2aae30e3
No related branches found
No related tags found
1 merge request!115Resolve "Add authorization to socketio"
......@@ -5,7 +5,7 @@
"editor.tabCompletion": "on",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": false
"source.organizeImports": true
},
//python
"python.venvPath": "${workspaceFolder}\\server",
......
import React, { useEffect } from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import { BrowserRouter, Switch } from 'react-router-dom'
import { getTypes } from './actions/typesAction'
import { useAppDispatch } from './hooks'
import AdminPage from './pages/admin/AdminPage'
......@@ -27,21 +27,31 @@ const Main: React.FC = () => {
path="/editor/competition-id=:competitionId"
component={PresentationEditorPage}
/>
<Route exact path="/:code" component={ViewSelectPage} />
<SecureRoute authLevel={'competition'} exact path="/:code" component={ViewSelectPage} />
<SecureRoute
authLevel={'competition'}
exact
path="/participant/id=:id&code=:code"
path="/team/competition-id=:competitionId"
component={ParticipantViewPage}
/>
<SecureRoute
authLevel={'competition'}
exact
path="/presenter/id=:id&code=:code"
path="/operator/competition-id=:competitionId"
component={PresenterViewPage}
/>
<SecureRoute authLevel={'competition'} exact path="/judge/id=:id&code=:code" component={JudgeViewPage} />
<SecureRoute authLevel={'competition'} exact path="/audience/id=:id&code=:code" component={AudienceViewPage} />
<SecureRoute
authLevel={'competition'}
exact
path="/judge/competition-id=:competitionId"
component={JudgeViewPage}
/>
<SecureRoute
authLevel={'competition'}
exact
path="/audience/competition-id=:competitionId"
component={AudienceViewPage}
/>
</Switch>
</BrowserRouter>
)
......
......@@ -5,7 +5,6 @@ This file handles actions for the competitionLogin redux state
import axios from 'axios'
import { History } from 'history'
import { AppDispatch } from '../store'
import { AccountLoginModel } from './../interfaces/FormModels'
import Types from './types'
// Action creator to attempt to login with competition code
......@@ -14,10 +13,13 @@ export const loginCompetition = (code: string, history: History) => async (dispa
await axios
.post('/api/auth/login/code', { code })
.then((res) => {
console.log(code, res.data[0])
const token = `Bearer ${res.data.access_token}`
localStorage.setItem('competitionToken', token) //setting token to local storage
axios.defaults.headers.common['Authorization'] = token //setting authorize token to header in axios
console.log(code, res.data)
dispatch({ type: Types.CLEAR_COMPETITION_LOGIN_ERRORS }) // no error
// history.push('/admin') //redirecting to admin page after login success
if (res.data && res.data[0] && res.data[0].view_type_id) {
if (res.data && res.data.view_type_id) {
history.push(`/${code}`)
}
})
......
......@@ -74,6 +74,7 @@ const AdminView: React.FC = () => {
dispatch(getRoles())
dispatch(getTypes())
dispatch(getStatistics())
axios.get('/api/competitions/1/codes').then((res) => console.log(res.data.items))
}, [])
const menuAdminItems = [
......
import Button from '@material-ui/core/Button'
import React, { useEffect, useState } from 'react'
import { Link, useRouteMatch } from 'react-router-dom'
import { ViewSelectButtonGroup, ViewSelectContainer } from './styled'
import { useParams } from 'react-router-dom'
import { CircularProgress, Typography } from '@material-ui/core'
import ParticipantViewPage from './ParticipantViewPage'
import axios from 'axios'
import PresenterViewPage from './PresenterViewPage'
import JudgeViewPage from './JudgeViewPage'
import AudienceViewPage from './AudienceViewPage'
import React, { useEffect, useState } from 'react'
import { Redirect, useHistory, useParams } from 'react-router-dom'
import { loginCompetition } from '../../actions/competitionLogin'
import { useAppDispatch, useAppSelector } from '../../hooks'
import { getPresentationCompetition, setPresentationCode } from '../../actions/presentation'
import { ViewSelectButtonGroup, ViewSelectContainer } from './styled'
interface ViewSelectParams {
code: string
}
const ViewSelectPage: React.FC = () => {
const dispatch = useAppDispatch()
const history = useHistory()
const [loading, setLoading] = useState(true)
const [error, setError] = useState(false)
const [viewTypeId, setViewTypeId] = useState(undefined)
......@@ -29,11 +23,13 @@ const ViewSelectPage: React.FC = () => {
if (competitionId) {
switch (viewType) {
case 'Team':
return <ParticipantViewPage />
return <Redirect to={`/team/${competitionId}`} />
case 'Judge':
return <JudgeViewPage code={code} competitionId={competitionId} />
return <Redirect to={`/judge/${competitionId}`} />
case 'Audience':
return <AudienceViewPage />
return <Redirect to={`/audience/${competitionId}`} />
case 'Operator':
return <Redirect to={`/operator/${competitionId}`} />
default:
return <Typography>Inkorrekt vy</Typography>
}
......@@ -41,7 +37,8 @@ const ViewSelectPage: React.FC = () => {
}
useEffect(() => {
axios
dispatch(loginCompetition(code, history))
/* axios
.post('/api/auth/login/code', { code })
.then((response) => {
setLoading(false)
......@@ -53,7 +50,7 @@ const ViewSelectPage: React.FC = () => {
.catch(() => {
setLoading(false)
setError(true)
})
}) */
}, [])
return (
......
......@@ -5,25 +5,34 @@ interface UIError {
message: string
}
interface UserState {
interface CompetitionLoginState {
loading: boolean
errors: null | UIError
authenticated: boolean
}
const initialState: UserState = {
const initialState: CompetitionLoginState = {
loading: false,
errors: null,
authenticated: false,
}
export default function (state = initialState, action: AnyAction) {
switch (action.type) {
case Types.SET_COMPETITION_LOGIN_AUTHENTICATED:
return {
...state,
authenticated: true,
}
case Types.SET_COMPETITION_LOGIN_ERRORS:
return {
...state,
errors: action.payload as UIError,
loading: false,
}
case Types.CLEAR_COMPETITION_LOGIN_ERRORS:
return {
...state,
loading: false,
errors: null,
}
......
......@@ -26,6 +26,7 @@ const SecureRoute: React.FC<SecureRouteProps> = ({
} else {
await CheckAuthenticationCompetition()
}
console.log('initialized')
setInitialized(true)
}
waitForAuthentication()
......
......@@ -2,7 +2,6 @@ import axios from 'axios'
import jwtDecode from 'jwt-decode'
import { logoutCompetition } from '../actions/competitionLogin'
import Types from '../actions/types'
import { logoutUser } from '../actions/user'
import store from '../store'
const UnAuthorized = async () => {
......@@ -10,9 +9,11 @@ const UnAuthorized = async () => {
}
export const CheckAuthenticationCompetition = async () => {
console.log('checkAuthComp')
const authToken = localStorage.competitionToken
if (authToken) {
const decodedToken: any = jwtDecode(authToken)
console.log(decodedToken)
if (decodedToken.exp * 1000 >= Date.now()) {
axios.defaults.headers.common['Authorization'] = authToken
await axios
......
from datetime import timedelta
import app.core.http_codes as codes
import app.database.controller as dbc
from app.apis import item_response, protect_route, text_response
from app.core import sockets
from app.core.codes import verify_code
from app.core.dto import AuthDTO, CodeDTO
from flask_jwt_extended import (
create_access_token,
create_refresh_token,
get_jwt_identity,
get_raw_jwt,
jwt_refresh_token_required,
)
from flask_restx import Resource
from flask_restx import inputs, reqparse
from datetime import timedelta
from app.core import sockets
from flask_jwt_extended import (create_access_token, create_refresh_token,
get_jwt_identity, get_raw_jwt,
jwt_refresh_token_required)
from flask_restx import Resource, inputs, reqparse
api = AuthDTO.api
schema = AuthDTO.schema
......@@ -95,9 +91,10 @@ class AuthLoginCode(Resource):
api.abort(codes.UNAUTHORIZED, "Invalid code")
item_code = dbc.get.code_by_code(code)
if item_code.competition_id not in sockets.presentations:
api.abort(codes.UNAUTHORIZED, "Competition not active")
if item_code.view_type_id != 4:
if item_code.competition_id not in sockets.presentations:
api.abort(codes.UNAUTHORIZED, "Competition not active")
access_token = create_access_token(
item_code.id, user_claims=get_code_claims(item_code), expires_delta=timedelta(hours=8)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment