Commit 8970142c authored by Richard Blechinger's avatar Richard Blechinger
Browse files

Auth wall and permission implementation. Minor cleanups in design

parent 8ba13dab
...@@ -8077,9 +8077,9 @@ ...@@ -8077,9 +8077,9 @@
} }
}, },
"jquery": { "jquery": {
"version": "3.4.1", "version": "3.5.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
"integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==" "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
}, },
"js-levenshtein": { "js-levenshtein": {
"version": "1.1.6", "version": "1.1.6",
...@@ -13548,6 +13548,11 @@ ...@@ -13548,6 +13548,11 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true "dev": true
}, },
"vue-toast-notification": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/vue-toast-notification/-/vue-toast-notification-0.6.0.tgz",
"integrity": "sha512-GSXLTemx/+YLDpeObuMcz+gQ6NxvBcJxGhj5PB8CZDDBUQWbeAp0ZUPZEixDun/GtbxBOA9jLxo4MFPHTbIBYw=="
},
"vuejs-logger": { "vuejs-logger": {
"version": "1.5.4", "version": "1.5.4",
"resolved": "https://registry.npmjs.org/vuejs-logger/-/vuejs-logger-1.5.4.tgz", "resolved": "https://registry.npmjs.org/vuejs-logger/-/vuejs-logger-1.5.4.tgz",
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>dboard</title> <title>AURA Dashboard</title>
</head> </head>
<body> <body>
<noscript> <noscript>
......
<template> <template>
<div id="app" class="tw-flex tw-flex-col tw-min-h-screen" :key="localeKey"> <div id="app" class="tw-flex tw-flex-col tw-min-h-screen" :key="localeKey">
<app-header <app-header
:modules="modules" :modules="modules"
:user="user" :user="user"
/> />
<div class="tw-flex-1 tw-flex tw-my-8"> <div class="tw-flex-1 tw-flex tw-my-8">
<router-view/> <router-view :modules="modules" :user="user"/>
</div> </div>
<app-footer /> <app-footer :modules="modules"/>
</div> </div>
</template> </template>
<script> <script>
import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css' import 'bootstrap-vue/dist/bootstrap-vue.css'
import { translationVm } from '@/plugins/translation' import {translationVm} from '@/plugins/translation'
import header from './components/Header.vue' import header from './components/Header.vue'
import footer from './components/Footer.vue' import footer from './components/Footer.vue'
export default { export default {
name: 'App', name: 'App',
components: { components: {
'app-header': header, 'app-header': header,
'app-footer': footer 'app-footer': footer
}, },
computed: { computed: {
userOIDC () { return this.$store.state.auth.userOIDC }, userOIDC() {
user () { return this.$store.state.auth.user }, return this.$store.state.auth.userOIDC
localeKey: () => translationVm.activeLocale, },
modules: function () { user() {
// Logged out return this.$store.state.auth.user
let modules = [ },
{ slug: 'home', title: this.$t('navigation.home') }, localeKey: () => translationVm.activeLocale,
] modules: function () {
// Logged out
if (this.user.logged_in === true) { let modules = []
modules = (this.user.steeringUser && this.user.steeringUser.is_superuser)
// Super user // All icons used are taken from the Tango Project, which put them into public domain:
? [ { slug: 'home', title: this.$t('navigation.home') }, // http://tango.freedesktop.org
{ slug: 'shows', title: this.$t('navigation.shows') },
{ slug: 'files', title: this.$t('navigation.filesPlaylists') }, if (this.user.logged_in === true) {
{ slug: 'calendar', title: this.$t('navigation.calendar') }, ] modules = (this.user.steeringUser && this.user.steeringUser.is_superuser)
// Regular user // Super user
: [ { slug: 'home', title: this.$t('navigation.home') }, ? {
{ slug: 'shows', title: this.$t('navigation.shows') }, main: [
{ slug: 'files', title: this.$t('navigation.filesPlaylists') }, ] {
} icon: '/assets/applications-multimedia.png',
slug: 'shows',
return modules title: this.$t('navigation.shows')
}, },
}, {
created () { icon: '/assets/audio-x-generic.png',
this.$store.dispatch('auth/oidcInit') slug: 'files',
}, title: this.$t('navigation.filesPlaylists')
methods: { },
signIn () { {
this.$store.dispatch('auth/signinRedirect') icon: '/assets/x-office-calendar.png',
}, slug: 'calendar',
signOut () { title: this.$t('navigation.calendar')
this.$store.dispatch('auth/signoutRedirect') },
}, ],
}
} footer: [
{
slug: 'settings',
title: this.$t('navigation.settings'),
},
{
slug: 'help',
title: this.$t('navigation.help'),
}
]
}
// Regular user
: {
main: [
{
icon: '/assets/applications-multimedia.png',
slug: 'shows',
title: this.$t('navigation.shows')
},
{
icon: '/assets/audio-x-generic.png',
slug: 'files',
title: this.$t('navigation.filesPlaylists')
},
],
footer: [
{
slug: 'help',
title: this.$t('navigation.help'),
}
]
}
}
return modules
},
},
created() {
this.$store.dispatch('auth/oidcInit')
},
methods: {
signIn() {
this.$store.dispatch('auth/signinRedirect')
},
signOut() {
this.$store.dispatch('auth/signoutRedirect')
},
}
}
</script> </script>
<style> <style>
html, body { html, body {
min-height: 100vh; min-height: 100vh;
} }
#app {
color: #2e3436; #app {
} color: #2e3436;
/* }
#app .content-width {
margin: auto; /*
width: 920px; #app .content-width {
max-width: 920px; margin: auto;
} width: 920px;
*/ max-width: 920px;
}
*/
</style> </style>
...@@ -488,7 +488,6 @@ ...@@ -488,7 +488,6 @@
editPlaylist() { editPlaylist() {
let playlist = this.getPlaylistById(this.id); let playlist = this.getPlaylistById(this.id);
console.log("AAAAA", playlist);
if (!playlist) { if (!playlist) {
this.$router.push({ name: 'addPlaylist' }) this.$router.push({ name: 'addPlaylist' })
......
<template> <template>
<auth-wall>
<b-container> <b-container>
<show-selector <show-selector
ref="showSelector" ref="showSelector"
...@@ -92,21 +93,25 @@ ...@@ -92,21 +93,25 @@
ref="appModalEmissionManagerEdit" ref="appModalEmissionManagerEdit"
/> />
</b-container> </b-container>
</auth-wall>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { FullCalendar } from 'vue-full-calendar' import { FullCalendar } from 'vue-full-calendar'
import 'fullcalendar/dist/fullcalendar.css' import 'fullcalendar/dist/fullcalendar.css'
import showSelector from '../components/ShowSelector.vue'
import modalEmissionManagerCreate from '../components/emissions/ModalCreate.vue' import showSelector from '@/components/ShowSelector.vue'
import modalEmissionManagerResolve from '../components/emissions/ModalResolve.vue' import modalEmissionManagerCreate from '@/components/emissions/ModalCreate.vue'
import modalEmissionManagerEdit from '../components/emissions/ModalEdit.vue' import modalEmissionManagerResolve from '@/components/emissions/ModalResolve.vue'
import rrules from '../mixins/rrules' import modalEmissionManagerEdit from '@/components/emissions/ModalEdit.vue'
import AuthWall from '@/components/AuthWall.vue'
import rrules from '@/mixins/rrules'
export default { export default {
components: { components: {
FullCalendar, FullCalendar,
AuthWall,
'show-selector': showSelector, 'show-selector': showSelector,
'app-modalEmissionManagerCreate': modalEmissionManagerCreate, 'app-modalEmissionManagerCreate': modalEmissionManagerCreate,
'app-modalEmissionManagerResolve': modalEmissionManagerResolve, 'app-modalEmissionManagerResolve': modalEmissionManagerResolve,
...@@ -177,6 +182,8 @@ export default { ...@@ -177,6 +182,8 @@ export default {
}, },
created () { created () {
this.$store.dispatch('shows/fetchShows', { this.$store.dispatch('shows/fetchShows', {
callback: () => { callback: () => {
this.showHasSwitched() this.showHasSwitched()
......
<template> <template>
<b-container class="tw-self-center"> <b-container class="tw-self-center">
<div v-if="$parent.user.logged_in === true"> <div v-if="$parent.user.logged_in === true">
<div align="center"> <div align="center">
<h1>{{ $t('home.welcome') }}</h1> <h1>{{ $t('home.welcome') }}</h1>
<p>Here are some infos for you on how to use this interface...</p> <p>Here are some infos for you on how to use this interface...</p>
<br> <br>
</div> </div>
<div class="tw-mx-auto tw-max-w-4xl tw-grid sm:tw-grid-cols-2 md:tw-grid-cols-4 tw-gap-8 tw-text-center"> <div :class="{
<router-link to="shows"> 'tw-mx-auto tw-grid sm:tw-grid-cols-2 tw-gap-8 tw-text-center': true,
<img src="/assets/applications-multimedia.png"> 'md:tw-grid-cols-3 tw-max-w-3xl': $parent.user.steeringUser.is_superuser,
<p>Schedule your shows</p> 'md:tw-grid-cols-2 tw-max-w-lg': !$parent.user.steeringUser.is_superuser
</router-link> }">
<router-link to="files"> <router-link v-for="mod in modules.main" :to="mod.slug" :key="mod.slug">
<img src="/assets/audio-x-generic.png"> <img :src="mod.icon">
<p>Manage files and playlists</p> <p>{{ mod.title }}</p>
</router-link> </router-link>
<router-link to="settings"> </div>
<img src="/assets/applications-system.png"> </div>
<p>Settings</p> <div
</router-link> v-else
<router-link to="help"> align="center"
<img src="/assets/help-browser.png"> >
<p>Help pages</p> <p>You are not logged in yet.</p>
</router-link> <b-button
</div> size="lg"
</div> variant="outline-secondary"
<div @click="$parent.signIn"
v-else >
align="center" Log in
> </b-button>
<p>You are not logged in yet.</p> </div>
<b-button </b-container>
size="lg"
variant="outline-secondary"
@click="$parent.signIn"
>
Log in
</b-button>
</div>
</b-container>
<!--
All icons used are taken from the Tango Project, which put them into public domain:
http://tango.freedesktop.org
-->
</template> </template>
<script> <script>
export default {} export default {
props: ['user', 'modules']
}
</script> </script>
<style> <style>
......
<template> <template>
<b-container align="center"> <auth-wall>
<h1>Dashboard Settings</h1> <b-container align="center">
<br><br> <h1>Dashboard Settings</h1>
<div style="border: 5px dotted #5c3566;"> <br><br>
<br><br> <div style="border: 5px dotted #5c3566;">
<p><b>By the mighty witchcraftry of the mother of time!</b></p> <br><br>
<p>This feature is not implemented yet.</p> <p><b>By the mighty witchcraftry of the mother of time!</b></p>
<br><br> <p>This feature is not implemented yet.</p>
</div> <br><br>
</b-container> </div>
</b-container>
</auth-wall>
</template> </template>
<script> <script>
export default {} import AuthWall from '@/components/AuthWall'
export default {
components: { AuthWall }
}
</script> </script>
<style> <style>
......
<template>
<div v-if="$store.state.auth.user.steeringUser" class="tw-w-full">
<slot></slot>
</div>
<div v-else class="tw-w-full tw-text-center">
{{ $t('loading') }}
</div>
</template>
<script>
export default {
created() {
const user = this.$store.state.auth.user.steeringUser;
// We might not have a user at load-time.
// In this case wait until the store gives us one.
if (user === null) {
this.$store.watch(
(state) => state.auth.user.steeringUser,
(user) => this.redirectToHome(user)
)
return;
}
this.redirectToHome(user);
},
methods: {
redirectToHome(user) {
if (!user.is_superuser) {
this.$toast.error(this.$t('auth.permissionError'), { position: 'bottom-left' })
this.$router.push({ name: 'home' })
}
}
}
}
</script>
<template> <template>
<footer class="tw-p-2 tw-bg-gray-800"> <footer class="tw-p-2 tw-bg-gray-800">
<b-container> <b-container>
<b-row> <b-row>
<b-col> <b-col>
aura/<b>dashboard v{{ version }}</b> | aura/<b>dashboard v{{ version }}</b>
<router-link to="/credits"> <span v-for="mod in modules.footer" :key="mod.slug">
Credits | <router-link :to="mod.slug">
</router-link> {{ mod.title }}
</b-col> </router-link>
<b-col align="right"> </span>
{{ $t('footer.tagline') }}
</b-col> | <router-link to="/credits">
</b-row> Credits
</b-container> </router-link>
</footer> </b-col>
<b-col align="right">
{{ $t('footer.tagline') }}
</b-col>
</b-row>
</b-container>
</footer>
</template> </template>
<script> <script>
export default { export default {
computed: { props: ["modules"],
version() { computed: {
console.log(process.env) version() {
return process.env.VUE_APP_VERSION return process.env.VUE_APP_VERSION
}
}
} }
}
}
</script> </script>
<style scoped> <style scoped>
footer { footer {
border-top: 1px solid #2e3436; border-top: 1px solid #2e3436;
color: rgba(255, 255, 255, 0.5); color: rgba(255, 255, 255, 0.5);
width: 100%; width: 100%;
margin-top: auto; margin-top: auto;
} }
a { a {
color: #cc149e; color: #cc149e;
} }
</style> </style>
<template> <template>
<header class="tw-bg-gray-800"> <header class="tw-bg-gray-800">