diff --git a/src/api/Dockerfile b/src/api/Dockerfile new file mode 100755 index 0000000..3d47a37 --- /dev/null +++ b/src/api/Dockerfile @@ -0,0 +1,9 @@ +FROM node:alpine +RUN mkdir -p /app +WORKDIR /app +COPY . /app +RUN cd /app +RUN yarn install +RUN yarn build +EXPOSE 3000 +CMD ["node", "dist/index.js"] diff --git a/src/api/kubernetesDeployment.json b/src/api/kubernetesDeployment.json index 05d219e..0e1df3c 100644 --- a/src/api/kubernetesDeployment.json +++ b/src/api/kubernetesDeployment.json @@ -12,19 +12,8 @@ "containers": [ { "name": "tezosacademy-api", - "image": "registry.digitalocean.com/octo/tezosacademy-api", - "imagePullPolicy": "Always", - "env": [ - { - "name": "TEST_KEY", - "valueFrom": { - "secretKeyRef": { - "name": "person", - "key": "TEST_KEY" - } - } - } - ] + "image": "registry.digitalocean.com/rtx/tezosacademy-api", + "imagePullPolicy": "Always" } ] } diff --git a/src/api/package.json b/src/api/package.json index f03d1e3..ee63af6 100644 --- a/src/api/package.json +++ b/src/api/package.json @@ -7,10 +7,10 @@ "build": "PORT=3000 NODE_ENV=production tsc", "analyze": "PORT=3000 NODE_ENV=production tsc && npx source-map-explorer 'build/static/js/*.js'", "docker-create": "doctl k8s cluster create --region fra1 --node-pool \"name=tezosacademy-api;size=s-1vcpu-2gb;count=1;auto-scale=true;min-nodes=1;max-nodes=3\" tezosacademy-api --wait && doctl kubernetes cluster kubeconfig save tezosacademy-api", - "docker-build": "docker build -t octo/tezosacademy-api . --no-cache", - "docker-run": "docker run --rm -it -p 3000:3000 octo/tezosacademy-api", - "docker-push": "doctl registry login && docker tag octo/tezosacademy-api registry.digitalocean.com/octo/tezosacademy-api && docker push registry.digitalocean.com/octo/tezosacademy-api", - "docker-patch": "doctl registry kubernetes-manifest | kubectl --context do-fra1-tezosacademy-api apply -f - && kubectl --context do-fra1-tezosacademy-api patch serviceaccount default -p '{\"imagePullSecrets\": [{\"name\": \"registry-octo\"}]}'", + "docker-build": "docker build -t rtx/tezosacademy-api . --no-cache", + "docker-run": "docker run --rm -it -p 3000:3000 rtx/tezosacademy-api", + "docker-push": "doctl registry login && docker tag rtx/tezosacademy-api registry.digitalocean.com/rtx/tezosacademy-api && docker push registry.digitalocean.com/rtx/tezosacademy-api", + "docker-patch": "doctl registry kubernetes-manifest | kubectl --context do-fra1-tezosacademy-api apply -f - && kubectl --context do-fra1-tezosacademy-api patch serviceaccount default -p '{\"imagePullSecrets\": [{\"name\": \"registry-rtx\"}]}'", "docker-secrets": "kubectl --context do-fra1-tezosacademy-api create secret generic person --from-env-file=.testenv", "docker-deploy": "kubectl --context do-fra1-tezosacademy-api apply -f kubernetesDeployment.json", "docker-serve": "kubectl --context do-fra1-tezosacademy-api apply -f kubernetesService.json", diff --git a/src/api/src/kubernetes.json b/src/api/src/kubernetes.json index 010ea3e..3dfad10 100644 --- a/src/api/src/kubernetes.json +++ b/src/api/src/kubernetes.json @@ -12,7 +12,7 @@ "containers": [ { "name": "tezosacademy-api", - "image": "registry.digitalocean.com/octo/tezosacademy-api", + "image": "registry.digitalocean.com/rtx/tezosacademy-api", "imagePullPolicy": "Always" } ], diff --git a/src/frontend/kubernetesDeployment.json b/src/frontend/kubernetesDeployment.json index a014496..9bece02 100644 --- a/src/frontend/kubernetesDeployment.json +++ b/src/frontend/kubernetesDeployment.json @@ -12,7 +12,7 @@ "containers": [ { "name": "tezosacademy-frontend", - "image": "registry.digitalocean.com/octo/tezosacademy-frontend", + "image": "registry.digitalocean.com/rtx/tezosacademy-frontend", "imagePullPolicy": "Always" } ] diff --git a/src/frontend/package.json b/src/frontend/package.json index 8dcc4ae..c86e24d 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -5,10 +5,10 @@ "start": "PORT=3000 NODE_ENV=development REACT_APP_BACKEND_URL=http://localhost:8080 react-scripts -r @cypress/instrument-cra start && open http://localhost:3000", "build": "INLINE_RUNTIME_CHUNK=false react-scripts build && cra-append-sw -s ./src/custom-sw.js", "docker-create": "doctl k8s cluster create --region fra1 --node-pool \"name=tezosacademy-frontend;size=s-1vcpu-2gb;count=1;auto-scale=true;min-nodes=1;max-nodes=3\" tezosacademy-frontend --wait && doctl kubernetes cluster kubeconfig save tezosacademy-frontend", - "docker-build": "yarn build && docker build -t octo/tezosacademy-frontend . --no-cache", - "docker-run": "docker run --rm -it -p 80:80 octo/tezosacademy-frontend", - "docker-push": "doctl registry login && docker tag octo/tezosacademy-frontend registry.digitalocean.com/octo/tezosacademy-frontend && docker push registry.digitalocean.com/octo/tezosacademy-frontend", - "docker-patch": "doctl registry kubernetes-manifest | kubectl --context do-fra1-tezosacademy-frontend apply -f - && kubectl --context do-fra1-tezosacademy-frontend patch serviceaccount default -p '{\"imagePullSecrets\": [{\"name\": \"registry-octo\"}]}'", + "docker-build": "yarn build && docker build -t rtx/tezosacademy-frontend . --no-cache", + "docker-run": "docker run --rm -it -p 80:80 rtx/tezosacademy-frontend", + "docker-push": "doctl registry login && docker tag rtx/tezosacademy-frontend registry.digitalocean.com/rtx/tezosacademy-frontend && docker push registry.digitalocean.com/rtx/tezosacademy-frontend", + "docker-patch": "doctl registry kubernetes-manifest | kubectl --context do-fra1-tezosacademy-frontend apply -f - && kubectl --context do-fra1-tezosacademy-frontend patch serviceaccount default -p '{\"imagePullSecrets\": [{\"name\": \"registry-rtx\"}]}'", "docker-secrets": "kubectl --context do-fra1-tezosacademy-frontend create secret generic person --from-env-file=.env", "docker-deploy": "kubectl --context do-fra1-tezosacademy-frontend apply -f kubernetesDeployment.json", "docker-serve": "kubectl --context do-fra1-tezosacademy-frontend apply -f kubernetesService.json", diff --git a/src/frontend/src/app/App.offline.tsx b/src/frontend/src/app/App.offline.tsx index c005b54..34e7e56 100644 --- a/src/frontend/src/app/App.offline.tsx +++ b/src/frontend/src/app/App.offline.tsx @@ -3,7 +3,7 @@ import * as React from 'react' import * as ReactDOM from 'react-dom' import { Root, store } from '../index' -import { restore } from './App.actions' +import { redirect, reset, restore } from './App.actions' import { showToaster } from './App.components/Toaster/Toaster.actions' import { ERROR } from './App.components/Toaster/Toaster.constants' @@ -13,7 +13,19 @@ const discard = (error: any, _action: any, _retries: any) => { if (response && response.error && typeof response.error === 'string') message = response.error else if (response && typeof response === 'string') message = response + console.error('discard', response.status, response.error) + + // Rename error + if (response.error === 'jwt expired' || response.error === 'jwt malformed') message = 'Session expired' + + // Actions on server errors if (response) store.dispatch(showToaster(ERROR, message, 'Contact support if needed')) + if (response.error === 'Password expired') store.dispatch(redirect('/forgot-password')) + if (response.error === 'jwt expired' || response.error === 'jwt malformed' || response.error === 'Not logged in') { + store.dispatch(reset()) + store.dispatch(redirect('/login')) + } + if (!request) throw error if (!response) return false return 400 <= response.status && response.status < 500 @@ -32,17 +44,18 @@ export const storeOfflineConfig = { persistOptions: { blacklist: ['router'], }, + //returnPromises: true, } -export const reduxOfflineThunkMiddleware = () => (storex: any) => (next: any) => (action: any) => { +export const reduxOfflineThunkMiddleware = () => (_: any) => (next: any) => (action: any) => { if (action && action.type === 'Offline/JS_ERROR') console.error(action.meta.error) - const result = next(action) + if (action) next(action) - if (action.meta && action.meta.thunks && action.meta.thunks.length > 0) { + if (action && action.meta && action.meta.thunks && action.meta.thunks.length > 0) { action.meta.thunks.forEach((thunk: any) => { if (!!thunk) store.dispatch(thunk) }) } - return result + // return action ? next(action) : next() }