Skip to content

Commit

Permalink
Доступность сервера и контроль авторизации
Browse files Browse the repository at this point in the history
  • Loading branch information
mikhailprivalov committed May 29, 2021
1 parent 239a1ec commit 89d125e
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 24 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ on:
jobs:
build:
runs-on: ubuntu-latest
env:
SECRET_KEY: 'COMMIT_${SHORT_SHA}'

services:
postgres:
Expand Down
1 change: 0 additions & 1 deletion api/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from django.contrib.auth import authenticate, login
from django.http import JsonResponse
from django.middleware.csrf import CsrfViewMiddleware

import slog.models as slog
from users.models import DoctorProfile
Expand Down
1 change: 1 addition & 0 deletions api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ def current_user_info(request):
"department": {"pk": -1, "title": ""},
"groups": [],
"user_services": [],
"loading": False,
}
if ret["auth"]:
def fill_user_data():
Expand Down
9 changes: 7 additions & 2 deletions l2-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
</div>
</div>
</transition>

<CheckBackend />
</div>
</template>

Expand All @@ -23,10 +25,11 @@ import Vue from 'vue';
import Component from 'vue-class-component';
import { mapGetters } from 'vuex';
import Navbar from '@/components/Navbar.vue';
import CheckBackend from '@/ui-cards/CheckBackend.vue';
@Component({
components: { Navbar },
computed: mapGetters(['inLoading', 'fullPageLoader']),
components: { CheckBackend, Navbar },
computed: mapGetters(['inLoading', 'fullPageLoader', 'authenticated']),
metaInfo() {
return {
title: `${this.$route.meta.title || 'L2'} — ${this.$orgTitle()}`,
Expand All @@ -37,6 +40,8 @@ export default class App extends Vue {
inLoading: boolean;
fullPageLoader: boolean;
authenticated: boolean;
}
</script>

Expand Down
34 changes: 18 additions & 16 deletions l2-frontend/src/mainWithRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const router = new Router({
},
{
path: '/ui/menu',
name: 'login',
name: 'menu',
component: () => import('@/pages/MenuPage.vue'),
meta: {
narrowLayout: true,
Expand All @@ -49,15 +49,29 @@ const router = new Router({
});

router.beforeEach(async (to, from, next) => {
await router.app.$store.dispatch(actions.RESET_G_LOADING);
if (to.fullPath.startsWith('/ui') || to.fullPath.startsWith('ui')) {
await router.app.$store.dispatch(actions.RESET_G_LOADING);
await router.app.$store.dispatch(actions.INC_G_LOADING);

await router.app.$store.dispatch(actions.INC_G_LOADING);
await router.app.$store.dispatch(actions.GET_USER_DATA, { loadMenu: true });
await router.app.$store.dispatch(actions.DEC_G_LOADING);

next();
if (
to.name !== 'login'
&& !to.matched.some(record => record.meta.allowWithoutLogin)
&& !router.app.$store.getters.authenticated
) {
next({ name: 'login' });
} else if (
to.name === 'login'
&& router.app.$store.getters.authenticated
) {
const urlParams = new URLSearchParams(window.location.search);
const nextPath = urlParams.get('next');
next(nextPath || '/ui/menu');
} else {
next();
}
} else {
window.location.href = to.fullPath;
}
Expand All @@ -67,18 +81,6 @@ router.afterEach(async () => {
await router.app.$store.dispatch(actions.DEC_G_LOADING);
});

router.beforeEach((to, from, next) => {
if (
to.name !== 'login'
&& !to.matched.some(record => record.meta.allowWithoutLogin)
&& router.app.$store.getters.authenticated
) {
next({ name: 'login' });
} else {
next();
}
});

new Vue({
router,
store,
Expand Down
1 change: 0 additions & 1 deletion l2-frontend/src/pages/LoginPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ export default class LoginPage extends Vue {
}
}
// eslint-disable-next-line class-methods-use-this
afterOkAuth() {
const urlParams = new URLSearchParams(window.location.search);
const next = urlParams.get('next');
Expand Down
1 change: 0 additions & 1 deletion l2-frontend/src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import directory from './modules/directory';
import user from './modules/user';
import * as action_types from './action-types';
import * as mutation_types from './mutation-types';
import { RESET_LOADING } from './action-types';

Vue.use(Vuex);

Expand Down
6 changes: 5 additions & 1 deletion l2-frontend/src/store/modules/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const getters = {

const actions = {
async [actionsTypes.GET_USER_DATA]({ commit }, { loadMenu = false } = {}) {
commit(mutation_types.SET_USER_DATA, { loading: true });
const data = await user_point.getCurrentUserInfo();
commit(mutation_types.SET_USER_DATA, { data });
if (loadMenu) {
Expand All @@ -66,7 +67,10 @@ const actions = {

const mutations = {
[mutation_types.SET_USER_DATA](state, { data }) {
state.data = data;
state.data = {
...state.data,
...data,
};
},
[mutation_types.SET_MENU](state, { data }) {
state.menu = {
Expand Down
139 changes: 139 additions & 0 deletions l2-frontend/src/ui-cards/CheckBackend.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<template>
<div id="check-backend"/>
</template>

<script lang="ts">
import Vue from 'vue';
import { mapGetters } from 'vuex';
import Component from 'vue-class-component';
import * as actions from '@/store/action-types';
import { POSITION } from 'vue-toastification/src/ts/constants';
@Component({
computed: mapGetters(['authenticated', 'user_data']),
data() {
return {
userIsIdle: false,
hasError: false,
aliveTimer: null,
};
},
})
export default class CheckBackend extends Vue {
authenticated: boolean;
userIsIdle: boolean;
hasError: boolean;
aliveTimer: number | void;
user_data: any;
mounted() {
this.check();
}
check() {
if (this.aliveTimer) {
clearTimeout(this.aliveTimer);
}
if (this.$route.name === 'login' && this.authenticated) {
const urlParams = new URLSearchParams(window.location.search);
const nextPath = urlParams.get('next');
this.$router.push(nextPath || { name: 'menu' });
return;
}
window.$.ajax({
method: 'GET',
url: '/mainmenu/',
cache: false,
statusCode: {
500: () => {
this.$toast.clear();
this.$toast.error('Сервер недоступен. Ошибка 500. Ожидайте доступность сервера.', {
position: POSITION.BOTTOM_RIGHT,
timeout: this.userIsIdle ? 300000 : 20000,
icon: true,
});
if (!this.hasError) {
this.hasError = true;
this.$store.dispatch(actions.INC_LOADING);
}
window.$('input').blur();
},
502: () => {
this.$toast.clear();
this.$toast.error('Сервер недоступен. Ошибка 502. Ожидайте доступность сервера.', {
position: POSITION.BOTTOM_RIGHT,
timeout: this.userIsIdle ? 300000 : 20000,
icon: true,
});
if (!this.hasError) {
this.hasError = true;
this.$store.dispatch(actions.INC_LOADING);
}
window.$('input').blur();
},
},
}).fail(jqXHR => {
if (jqXHR.status === 502 || jqXHR.status === 500) return;
this.$toast.clear();
this.$toast.error('Сервер недоступен. Ошибка связи с сервером. Сообщите администратору о проблеме', {
position: POSITION.BOTTOM_RIGHT,
timeout: this.userIsIdle ? 300000 : 20000,
icon: true,
});
if (!this.hasError) {
this.hasError = true;
this.$store.dispatch(actions.INC_LOADING);
}
window.$('input').blur();
}).done(data => {
if (!this.authenticated && String(data).startsWith('OK')) {
const urlParams = new URLSearchParams(window.location.search);
const nextPath = urlParams.get('next');
this.$router.push(nextPath || { name: 'menu' });
}
if (this.authenticated && !String(data).startsWith('OK')) {
this.$router.push(`/ui/login?next=${encodeURIComponent(window.location.href.replace(window.location.origin, ''))}`);
return;
}
if (
this.authenticated
&& this.user_data
&& !this.user_data.loading
&& data !== `OK:${this.user_data.username}`
) {
window.location.reload();
}
if (this.hasError) {
this.$toast.clear();
this.hasError = false;
this.$toast.success('Сервер доступен', {
position: POSITION.BOTTOM_RIGHT,
timeout: 10000,
icon: true,
});
this.$store.dispatch(actions.DEC_LOADING);
}
}).always(() => {
this.aliveTimer = setTimeout(() => this.check(), this.userIsIdle ? 300000 : 20000);
});
}
}
</script>

<style scoped>
#check-backend {
display: none;
}
</style>
2 changes: 1 addition & 1 deletion mainmenu/templates/vuebase.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
</head>
<body>
<div id="app"></div>
<script src="{% static 'js/jquery.slim.min.js' %}"></script>
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% manifest 'chunk-common.js' %}"></script>
<script src="{% manifest 'chunk-vendors.js' %}"></script>
Expand Down
2 changes: 1 addition & 1 deletion mainmenu/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
def dashboard(request):
if not request.is_ajax():
return redirect('/ui/menu')
return HttpResponse("OK")
return HttpResponse(f"OK:{request.user.username}")


@login_required
Expand Down

0 comments on commit 89d125e

Please sign in to comment.