This commit is contained in:
Kekskurse 2019-06-20 18:04:08 +02:00
parent 42d2973a05
commit 50ef516ed6
19 changed files with 1174 additions and 52 deletions

5
package-lock.json generated
View file

@ -10918,6 +10918,11 @@
"vue-style-loader": "^4.1.0" "vue-style-loader": "^4.1.0"
} }
}, },
"vue-router": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.6.tgz",
"integrity": "sha512-Ox0ciFLswtSGRTHYhGvx2L44sVbTPNS+uD2kRISuo8B39Y79rOo0Kw0hzupTmiVtftQYCZl87mwldhh2L9Aquw=="
},
"vue-style-loader": { "vue-style-loader": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",

View file

@ -11,6 +11,7 @@
"axios": "^0.18.0", "axios": "^0.18.0",
"core-js": "^2.6.5", "core-js": "^2.6.5",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-router": "^3.0.6",
"vuetify": "^1.5.5", "vuetify": "^1.5.5",
"vuex": "^3.1.1" "vuex": "^3.1.1"
}, },

View file

@ -1,48 +1,30 @@
<template> <template>
<v-app v-scroll="handleScroll" v-if="$store.state.settingsLoaded"> <v-app >
<v-toolbar app :flat="flat" :prominent="big" :dense="!big" :color="bgcolor" clipped-left > <div v-if="$store.getters.getAllDataLoaded">
<v-toolbar-title class="headline text-uppercase" > <Menu></Menu>
<span>{{ nameBig }}</span> <MenuMobile></MenuMobile>
<span class="font-weight-light">{{ nameSmall }}</span>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items class="hidden-sm-and-down">
<v-btn
v-for="item in menu"
:key="item.icon"
:to="item.link"
flat
>{{ item.title }}</v-btn>
</v-toolbar-items>
<v-menu class="hidden-md-and-up">
<v-toolbar-side-icon slot="activator"></v-toolbar-side-icon>
<v-list>
<v-list-tile v-for="item in menu" :key="item.icon">
<v-list-tile-content>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-menu>
</v-toolbar>
<v-content style="background-color: #fff;"> <v-content style="background-color: #fff;">
<Startpage/> <router-view></router-view>
</v-content> </v-content>
</div>
<div v-if="!$store.getters.getAllDataLoaded">
Loading ...
</div>
</v-app> </v-app>
</template> </template>
<script> <script>
import HelloWorld from './components/HelloWorld' import Menu from "./components/Menu";
import Startpage from './components/Startpage' import MenuMobile from "./components/MenuMobile"
export default { export default {
name: 'App', name: 'App',
components: { components: {
HelloWorld, 'Menu': Menu,
Startpage 'MenuMobile': MenuMobile
}, },
data () { data () {
return { return {
@ -69,7 +51,7 @@ export default {
} }
}, },
methods: { methods: {
handleScroll: function (evt, el) { /*handleScroll: function (evt, el) {
if(evt.pageY > 100) { if(evt.pageY > 100) {
this.big = false; this.big = false;
this.bgcolor = "#fff"; this.bgcolor = "#fff";
@ -79,10 +61,11 @@ export default {
this.bgcolor = "transparent"; this.bgcolor = "transparent";
this.flat = true; this.flat = true;
} }
} }*/
}, },
mounted: function () { mounted: function () {
this.$store.dispatch('checkAccount');
console.log("MOUNTED");
this.$store.dispatch('getSettings').then(() => { this.$store.dispatch('getSettings').then(() => {
this.nameBig = this.$store.getters.getSettingValue("name_big"); this.nameBig = this.$store.getters.getSettingValue("name_big");
this.nameSmall = this.$store.getters.getSettingValue("name_small"); this.nameSmall = this.$store.getters.getSettingValue("name_small");

96
src/components/Login.vue Normal file
View file

@ -0,0 +1,96 @@
<template>
<div>
<h1>Login</h1>
<v-alert
:value="true"
type="error"
v-if="errorMessage"
>
{{ errorMessage }}
</v-alert>
<p>Login to your <span v-if="loginToService">{{ serviceName }}</span><span v-if="!loginToService">{{nameBig}}{{nameSmall}}</span> with your credentials.</p>
<v-text-field
label="Username"
value=""
v-model="username"
></v-text-field>
<v-text-field
label="Password"
value=""
type="password"
v-model="password"
></v-text-field>
<v-checkbox
v-model="logintoMainAccount"
:label="loginText"
v-if="loginToService"
disabled="true"
></v-checkbox>
<v-checkbox
v-model="allowSpaces"
label="Permanent Login at this Device"
v-if="showPermanentLogin()"
></v-checkbox>
<v-btn
color="success"
@click="login"
>
Login
</v-btn>
</div>
</template>
<script>
import UserService from '../services/User'
export default {
data () {
return {
username: '',
password: '',
errorMessage: '',
nameBig: '',
nameSmall: '',
loginText: '',
logintoMainAccount: true
}
},
props: [
'loginToService',
'serviceName'
],
methods: {
'login': function () {
UserService.login(this.username, this.password).then((res) => {
this.errorMessage = '';
UserService.setAccessToken(res.data.data["access_token"]);
console.log("Login ok, dispatch event");
this.$store.dispatch('checkAccount');
this.$emit('loggedIn')
}, (res) => {
this.errorMessage = res.response.data.msg;
});
},
showPermanentLogin: function () {
return false;
if(this.loginToService && this.logintoMainAccount) {
return true;
}
if(!this.loginToService) {
return true;
}
return false;
}
},
mounted: function() {
this.nameBig = this.$store.getters.getSettingValue("name_big");
this.nameSmall = this.$store.getters.getSettingValue("name_small");
this.loginText = "Login to "+this.nameBig+this.nameSmall+" too"
}
}
</script>
<style>
</style>

155
src/components/Menu.vue Normal file
View file

@ -0,0 +1,155 @@
<template>
<v-toolbar v-scroll="handleScroll" app :flat="flat" :prominent="big" :dense="!big" :color="bgcolor" clipped-left >
<v-toolbar-title class="headline text-uppercase" >
<span>{{ nameBig }}</span>
<span class="font-weight-light">{{ nameSmall }}</span>
</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items class="hidden-sm-and-down">
<v-btn
v-if="this.$store.state.loggedIn && this.$store.getters.getMe.developer"
:to="{path: '/apps'}"
flat
>Apps</v-btn>
<v-btn
v-if="this.$store.state.loggedIn && this.$store.getters.getMe.admin"
:to="{path: '/admin'}"
flat
>Admin</v-btn>
<v-menu offset-y v-if="this.$store.state.loggedIn">
<template v-slot:activator="{ on }">
<v-btn
v-on="on"
flat
>
Profile
</v-btn>
</template>
<v-list>
<v-list-tile>
<v-list-tile-title @click="clickLoogut()">Logout</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
<v-btn
v-if="!this.$store.state.loggedIn"
:to="{path: '/login'}"
flat
>Login</v-btn>
<v-btn
v-if="!this.$store.state.loggedIn && this.$store.getters.getSettingValue('invites')"
:to="{path: '/invited'}"
flat
>Invited</v-btn>
<v-btn
v-if="!this.$store.state.loggedIn && this.$store.getters.getSettingValue('registration_possible')"
:to="{path: '/register'}"
flat
>Register</v-btn>
<!--<v-menu offset-y>
<template v-slot:activator="{ on }">
<v-btn
color="primary"
dark
v-on="on"
>
Dropdown
</v-btn>
</template>
<v-list>
<v-list-tile
v-for="(item, index) in menu"
:key="index"
@click=""
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>!-->
</v-toolbar-items>
<v-menu class="hidden-md-and-up">
<v-toolbar-side-icon slot="activator" @click.stop="toggleSideMenu()"></v-toolbar-side-icon>
</v-menu>
</v-toolbar>
</template>
<script>
import UserServie from '../services/User'
export default {
name: 'Menu',
components: {
},
data () {
return {
big: true,
bgcolor: "transparent",
flat: true,
nameBig: '',
nameSmall: '',
}
},
computed: {
setting: (name) => {
//this.$store.getters.getSettingValue(this.$store.state, name);
}
},
methods: {
toggleSideMenu: function() {
console.log("TOGGLE");
this.$store.state.sideMenu = !this.$store.state.sideMenu;
},
generateMenu: function () {
this.menu = [];
if(!this.$store.state.loggedIn) {
this.menu.push({ icon: 'home', title: 'Login' , link: "Login" });
if(this.$store.getters.getSettingValue("invites")) {
this.menu.push({ icon: 'home', title: 'Invited' , link: "Invited" });
}
if(this.$store.getters.getSettingValue("registration_possible")) {
this.menu.push({ icon: 'home', title: 'Register' , link: "Register" });
}
} else {
if(this.$store.getters.getMe.developer) {
this.menu.push({ icon: 'home', title: 'Apps' , link: "Apps" });
}
if(this.$store.getters.getMe.admin) {
this.menu.push({ icon: 'home', title: 'Admin' , link: "Admin" });
}
this.menu.push({ icon: 'home', title: 'Profile' , link: "profile", submenu: true, menu: [
{ icon: 'home', title: 'Logout' , link: "Logout" }
] });
}
},
handleScroll: function (evt, el) {
if(evt.pageY > 100) {
this.big = false;
this.bgcolor = "#fff";
this.flat = false;
} else {
this.big = true;
this.bgcolor = "transparent";
this.flat = true;
}
},
clickLoogut: function () {
UserServie.logout();
this.$store.dispatch('checkAccount')
this.$router.push({"path": "login"})
}
},
mounted: function () {
this.nameBig = this.$store.getters.getSettingValue("name_big");
this.nameSmall = this.$store.getters.getSettingValue("name_small");
this.generateMenu();
}
}
</script>

View file

@ -0,0 +1,146 @@
<template>
<v-navigation-drawer
stateless
absolute
value="true"
v-model="$store.state.sideMenu"
>
<v-list>
<v-list-tile>
<v-list-tile-action>
<v-icon>home</v-icon>
</v-list-tile-action>
<v-list-tile-title>Home</v-list-tile-title>
</v-list-tile>
<v-list-group
prepend-icon="account_circle"
value="true"
>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-title>Users</v-list-tile-title>
</v-list-tile>
</template>
<v-list-group
no-action
sub-group
value="true"
>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-title>Admin</v-list-tile-title>
</v-list-tile>
</template>
<v-list-tile
v-for="(admin, i) in admins"
:key="i"
@click=""
>
<v-list-tile-title v-text="admin[0]"></v-list-tile-title>
<v-list-tile-action>
<v-icon v-text="admin[1]"></v-icon>
</v-list-tile-action>
</v-list-tile>
</v-list-group>
<v-list-group
sub-group
no-action
>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-title>Actions</v-list-tile-title>
</v-list-tile>
</template>
<v-list-tile
v-for="(crud, i) in cruds"
:key="i"
@click=""
>
<v-list-tile-title v-text="crud[0]"></v-list-tile-title>
<v-list-tile-action>
<v-icon v-text="crud[1]"></v-icon>
</v-list-tile-action>
</v-list-tile>
</v-list-group>
</v-list-group>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
name: 'MenuMobile',
components: {
},
data () {
return {
big: true,
bgcolor: "transparent",
flat: true,
nameBig: '',
nameSmall: '',
sideMenu: this.$store.state.sideMenu,
menu: [
{ icon: 'home', title: 'Login' , link: "Login" },
{ icon: 'info', title: 'Invited' },
{ icon: 'warning', title: 'Register' }
],
menu2: [
{ icon: 'home', title: 'Apps' },
{ icon: 'info', title: 'Admin' },
{ icon: 'warning', title: 'Account' }
],
menu3: []
}
},
computed: {
setting: (name) => {
//this.$store.getters.getSettingValue(this.$store.state, name);
}
},
methods: {
generateMenu: function () {
this.menu = [];
if(!this.$store.state.loggedIn) {
this.menu.push({ icon: 'home', title: 'Login' , link: "Login" });
if(this.$store.getters.getSettingValue("invites")) {
this.menu.push({ icon: 'home', title: 'Invited' , link: "Invited" });
}
if(this.$store.getters.getSettingValue("registration_possible")) {
this.menu.push({ icon: 'home', title: 'Register' , link: "Register" });
}
} else {
if(this.$store.getters.getMe.developer) {
this.menu.push({ icon: 'home', title: 'Apps' , link: "Apps" });
}
if(this.$store.getters.getMe.admin) {
this.menu.push({ icon: 'home', title: 'Admin' , link: "Admin" });
}
this.menu.push({ icon: 'home', title: 'Profile' , link: "profile", submenu: true, menu: [
{ icon: 'home', title: 'Logout' , link: "Logout" }
] });
}
},
handleScroll: function (evt, el) {
if(evt.pageY > 100) {
this.big = false;
this.bgcolor = "#fff";
this.flat = false;
} else {
this.big = true;
this.bgcolor = "transparent";
this.flat = true;
}
}
},
mounted: function () {
this.nameBig = this.$store.getters.getSettingValue("name_big");
this.nameSmall = this.$store.getters.getSettingValue("name_small");
this.generateMenu();
}
}
</script>

View file

@ -2,6 +2,7 @@ import Vue from 'vue'
import './plugins/vuetify' import './plugins/vuetify'
import App from './App.vue' import App from './App.vue'
import store from './store/store' import store from './store/store'
import router from './router'
@ -20,5 +21,6 @@ Vue.config.productionTip = false
new Vue({ new Vue({
store, store,
router,
render: h => h(App), render: h => h(App),
}).$mount('#app') }).$mount('#app')

59
src/router/index.js Normal file
View file

@ -0,0 +1,59 @@
import Vue from 'vue'
import Router from 'vue-router'
import Startpage from '../views/Startpage'
import HelloWorld from '../components/HelloWorld'
import Login from '../views/Login'
import Dashboard from '../views/Dashboard'
import store from '../store/store';
import OAuthPermission from '../views/OAuthPermission'
import ListApps from '../views/ListApps'
import AppDetails from '../views/AppDetails'
Vue.use(Router)
function guard(to, from, next){
if(store.state.loggedIn) {
next(); // allow to enter route
} else{
store.state.redirectIfLoggedIn = to;
next('/login'); // go to '/login';
}
}
export default new Router({
routes: [
{
path: '/',
name: 'Startpage',
component: Startpage
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/oauth',
name: 'oAuthPermission',
component: OAuthPermission
},
{
beforeEnter: guard,
path: '/dashboard',
name: 'Dashboard',
component: Dashboard
},
{
beforeEnter: guard,
path: '/apps',
name: 'Apps',
component: ListApps
},
{
beforeEnter: guard,
path: '/apps/:id',
name: 'appDetails',
component: AppDetails
}
]
})

View file

@ -2,7 +2,8 @@ import axios from 'axios'
export default() => { export default() => {
return axios.create({ return axios.create({
baseURL: `http://localhost:8000/api/`, baseURL: `http://127.0.0.1:8000/api/`,
//baseURL: `https://account.keks.cloud/api/`,
withCredentials: false, withCredentials: false,
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',

22
src/services/Apps.js Normal file
View file

@ -0,0 +1,22 @@
import Api from '@/services/Api'
export default {
listApps (params) {
return Api().get('/v1/app')
},
getAppImage(id) {
return "https://account.keks.cloud/gui/apps/"+id+"/icon";
},
getApp(id) {
return Api().get('/v1/app/'+id)
},
getAppByKey(key) {
return Api().get("/v1/app/find?apiKey="+key);
},
getAccess(id) {
return Api().get('/v1/app/'+id+'/access?create=1')
},
allowAccess(id, redirect_uri, scope) {
return Api().post('/v1/app/'+id+'/access/allow', {redirect_uri: redirect_uri, scope:scope});
}
}

View file

@ -1,7 +1,7 @@
import Api from '@/services/Api' import Api from '@/services/Api'
export default { export default {
getSettings (params) { getPublicSettings (params) {
return Api().get('/v1/server/settings') return Api().get('/v1/server/settings')
} }
} }

21
src/services/User.js Normal file
View file

@ -0,0 +1,21 @@
import Api from '@/services/Api'
export default {
login(username, password) {
return Api().post('/v1/user/login', {username: username, password: password});
},
setAccessToken(access_token) {
localStorage.setItem('access_token', access_token)
Api().defaults.headers.common['Authorization'] = `Bearer ${access_token}`
},
getTokenFromStorage() {
this.setAccessToken(localStorage.getItem("access_token"));
},
me() {
return Api().get('/v1/user/me')
},
logout() {
localStorage.removeItem("access_token");
}
}

View file

@ -1,13 +1,19 @@
import Vuex from 'vuex' import Vuex from 'vuex'
import Vue from 'vue' import Vue from 'vue'
import ServerService from '../services/Server' import ServerService from '../services/Server'
import UserService from '../services/User'
Vue.use(Vuex) Vue.use(Vuex)
export default new Vuex.Store({ export default new Vuex.Store({
state: { state: {
settingsLoaded: false, settingsLoaded: false,
settings: [] // The TV inventory loggedIn : false,
meLoaded: false,
me: [],
redirectIfLoggedIn: null,
settings: [], // The TV inventory
sideMenu: false, //Toggle Side Menu on side Bar
}, },
getters: { getters: {
@ -21,6 +27,19 @@ export default new Vuex.Store({
return state.settings[i]["value"]; return state.settings[i]["value"];
} }
} }
},
getAllDataLoaded: (state) => {
var loaded = true;
if(!state.meLoaded) {
loaded = false;
}
if(!state.settingsLoaded) {
loaded = false;
}
return loaded;
},
getMe: (state) => {
return state.me;
} }
}, },
@ -28,19 +47,41 @@ export default new Vuex.Store({
setSettings: function(state, settings) { setSettings: function(state, settings) {
state.settings = settings; state.settings = settings;
state.settingsLoaded = true; state.settingsLoaded = true;
},
setMe: function(state, me) {
if(me == false) {
state.loggedIn = false;
state.meLoaded = true;
} else {
state.me = me;
state.loggedIn = true;
state.meLoaded = true;
} }
}, },
},
actions: { actions: {
getSettings: function (context) { getSettings: function (context) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
ServerService.getSettings().then((res) => { ServerService.getPublicSettings().then((res) => {
console.log(res);
context.commit('setSettings', res.data.data) context.commit('setSettings', res.data.data)
resolve() resolve()
}); });
}) })
},
checkAccount: function(context) {
UserService.getTokenFromStorage();
return new Promise((resolve, reject) => {
UserService.me().then((res) => {
console.log("GET USER DATA");
context.commit('setMe', res.data.data)
}, (res) => {
context.commit('setMe', false)
console.log("DONT GET USER DATA");
console.log(res.response.data)
})
})
} }
} }
}); });

192
src/views/AppDetails.vue Normal file
View file

@ -0,0 +1,192 @@
<template>
<div style="">
<v-container grid-list-md>
<v-layout row wrap>
<v-flex md12>
<h1>App {{ app.name }}</h1>
<v-card class="mx-auto" flat style="margin-top: 10px;">
<v-tabs
background-color="white"
color="fff"
left
>
<v-tab>Overview</v-tab>
<v-tab>API Access</v-tab>
<v-tab>Settings</v-tab>
<v-tab disabled>Users</v-tab>
<v-tab-item :key="1" :transition="false" :reverse-transition="false" >
<v-container style="padding-right: 0px; padding-left:0px;">
<img :src="imageUrl" style="float: right;width: 100px;">
<b>Description</b><br>
{{ app.description }}<br><br>
<a :href="app.url">{{ app.url }}</a>
</v-container>
</v-tab-item>
<v-tab-item :key="2" :transition="false" :reverse-transition="false">
<v-container style="padding-right: 0px; padding-left:0px;">
<h2>oAuth Token</h2>
<p>
Here are the oAuth API-Keys. You use this Keys to start the oAuth authorization work flow.
</p>
<v-text-field
label="API Key"
:value="app.apiKey"
hint="You can't edit this"
></v-text-field>
<v-text-field
label="API Secret"
:value="app.apiSecret"
hint="You can't edit this"
></v-text-field>
<br>
<h2>API Access</h2>
<p>
You can access the API to get informations about this APP with the following API Credentials:
<v-text-field
label="API Token"
value=""
disabled
></v-text-field>
<v-text-field
label="Refresh Token"
value=""
disabled
></v-text-field>
<h2>Development Access</h2>
<p>
To test the App you can use the following Developer Access and Refresh token, they are connected to your user.
<v-text-field
label="Access Token"
value=""
disabled
></v-text-field>
<v-text-field
label="Refresh Token"
value=""
disabled
></v-text-field>
</p>
</v-container>
</v-tab-item>
<v-tab-item :key="3" :transition="false" :reverse-transition="false">
<v-container style="padding-right: 0px; padding-left:0px;">
<v-layout>
<v-flex md8>
<v-text-field
label="App Name"
:value="app.name"
></v-text-field>
<v-text-field
label="URL"
:value="app.url"
></v-text-field>
<v-textarea
label="Description"
:value="app.description"
></v-textarea>
<v-text-field
label="Direct Login URL"
:value="app.directUrl"
hint="URL to login with this oAuth Provider"
></v-text-field>
<v-checkbox
v-model="app.properties.testingWarning"
label="Testing Warning"
disabled
></v-checkbox>
<v-checkbox
v-model="app.properties.untrustedWarning"
label="Untrusted Warning"
disabled
></v-checkbox>
<v-checkbox
v-model="app.properties.autoAccept"
label="Auto Accept"
disabled
></v-checkbox>
<v-checkbox
v-model="app.properties.showOnWebpage"
label="Show on Webpage"
disabled
></v-checkbox>
<v-checkbox
v-model="app.properties.stopAutoRedirect"
label="Stop Auto Redirect"
disabled
></v-checkbox>
<v-checkbox
v-model="app.properties.hideInAppList"
label="Hide in App List"
disabled
></v-checkbox>
<v-checkbox
v-model="app.properties.userCantRemoveApp"
label="Disabled user possible to remove App-Access"
disabled
></v-checkbox>
</v-flex>
<v-flex md4>
IMAGE
</v-flex>
</v-layout>
</v-container>
</v-tab-item>
<v-tab-item :key="4" :transition="false" :reverse-transition="false">
<v-container style="padding-right: 0px; padding-left:0px;">
</v-container>
</v-tab-item>
</v-tabs>
</v-card>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
import ServerService from '../services/Server'
import UserService from '../services/User'
import LoginComponent from '../components/Login'
import AppService from '../services/Apps'
export default {
data () {
return {
app: null,
imageUrl: ''
}
},
components: {
"Login": LoginComponent
},
methods: {
},
mounted: function() {
AppService.getApp(this.$route.params.id).then((res) => {
this.app = res.data.data;
})
this.imageUrl = AppService.getAppImage(this.$route.params.id);
}
}
</script>
<style>
</style>

89
src/views/Dashboard.vue Normal file
View file

@ -0,0 +1,89 @@
<template>
<div style="">
<v-container grid-list-md>
<v-layout row wrap>
<v-flex md12>
<h1>Dashboard</h1>
<br><br>
Hello {{$store.getters.getMe["username"]}},<br>
soon here will be an Dashboard.
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
import ServerService from '../services/Server'
import UserService from '../services/User'
export default {
data () {
return {
nameBig: '',
nameSmall: '',
username: '',
password: '',
errorMessage: ''
}
},
methods: {
'login': function () {
UserService.login(this.username, this.password).then((res) => {
this.errorMessage = '';
UserService.setAccessToken(res.data.data["access_token"]);
console.log("Login ok, dispatch event");
this.$store.dispatch('checkAccount');
}, (res) => {
this.errorMessage = res.response.data.msg;
});
}
},
mounted: function() {
this.nameBig = this.$store.getters.getSettingValue("name_big");
this.nameSmall = this.$store.getters.getSettingValue("name_small");
}
}
</script>
<style>
.header {
background-image: url('~@/assets/manhattan-407703_1920.jpg');
background-repeat: no-repeat;
margin-top: -100px;
height: 30vh;
text-align: center;
}
.header h1{
padding-top: 200px;
font-size: 56px !important;
font-weight: 400;
line-height: 32px !important;
letter-spacing: normal !important;
}
.header h1 .small{
font-weight: 300 !important;
}
.header h2{
padding-top: 30px;
font-size: 34px !important;
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
h1{
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
h2{
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
</style>

70
src/views/ListApps.vue Normal file
View file

@ -0,0 +1,70 @@
<template>
<div style="">
<v-container grid-list-md>
<v-layout row wrap>
<v-flex md12>
<h1>Apps</h1>
<br><br>
<p>Here you can Administrate your apps</p>
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex md4 text-xs-center v-for="(item, index) in apps">
<v-card>
<v-layout>
<v-flex xs5>
<v-img
:src="getImageUrl(item.id)"
height="125px"
contain
></v-img>
</v-flex>
<v-flex xs7>
<v-card-title primary-title>
<div>
<div class="headline">{{ item.name }}</div>
<div>{{ item.description }}</div>
</div>
</v-card-title>
</v-flex>
</v-layout>
<v-divider light></v-divider>
<v-card-actions class="pa-3">
<v-spacer></v-spacer>
<v-btn icon>
<v-icon @click="$router.push({name: 'appDetails', params: {id: item.id}})">settings</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
import AppService from '../services/Apps'
export default {
data () {
return {
apps: []
}
},
methods: {
getImageUrl: function(id) {
return AppService.getAppImage(id); // "https://account.keks.cloud/gui/apps/"+id+"/icon";
}
},
mounted: function() {
AppService.listApps().then((res) => {
this.apps = res.data.data;
console.log(this.apps);
});
}
}
</script>

100
src/views/Login.vue Normal file
View file

@ -0,0 +1,100 @@
<template>
<div style="">
<div class="header">
</div>
<v-container grid-list-md>
<v-layout row wrap>
<v-flex md4></v-flex>
<v-flex md4 v-if="!$store.state.loggedIn">
<Login></Login>
</v-flex>
<v-flex md4 v-if="$store.state.loggedIn">
<p>Hallo {{$store.getters.getMe["username"]}}, du bist bereits eingeloggt.</p>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
import ServerService from '../services/Server'
import UserService from '../services/User'
import LoginComponent from '../components/Login'
export default {
data () {
return {
nameBig: '',
nameSmall: '',
username: '',
password: '',
errorMessage: ''
}
},
components: {
"Login": LoginComponent
},
methods: {
'login': function () {
UserService.login(this.username, this.password).then((res) => {
this.errorMessage = '';
UserService.setAccessToken(res.data.data["access_token"]);
console.log("Login ok, dispatch event");
this.$store.dispatch('checkAccount');
}, (res) => {
this.errorMessage = res.response.data.msg;
});
}
},
mounted: function() {
console.log("REDIRECT: "+this.$store.state.redirectIfLoggedIn)
if(this.$store.state.loggedIn == true && this.$store.state.redirectIfLoggedIn != null) {
this.$router.push(this.$store.state.redirectIfLoggedIn);
}
this.nameBig = this.$store.getters.getSettingValue("name_big");
this.nameSmall = this.$store.getters.getSettingValue("name_small");
}
}
</script>
<style>
.header {
background-image: url('~@/assets/manhattan-407703_1920.jpg');
background-repeat: no-repeat;
margin-top: -100px;
height: 30vh;
text-align: center;
}
.header h1{
padding-top: 200px;
font-size: 56px !important;
font-weight: 400;
line-height: 32px !important;
letter-spacing: normal !important;
}
.header h1 .small{
font-weight: 300 !important;
}
.header h2{
padding-top: 30px;
font-size: 34px !important;
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
h1{
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
h2{
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
</style>

View file

@ -0,0 +1,141 @@
<template>
<div style="">
<div class="header">
</div>
<v-container grid-list-md>
<v-layout row wrap>
<v-flex md4></v-flex>
<v-flex md4 v-if="!$store.state.loggedIn">
<Login loginToService="true" serviceName="Jenkins" @loggedIn="getAppData();"></Login>
</v-flex>
<v-flex md4 v-if="$store.state.loggedIn && app != null">
<h1>Login to {{ app.name }}</h1>
<p>{{ app.description }}</p>
<hr>
<div style="margin-top:20px;margin-bottom:20px;">
This App get the following permissions:<br /><br />
<ul>
<li v-if="app.access.read_profile">Read your Profile information</li>
<li v-if="app.access.update_profile">>Update your Profile information</li>
<li v-if="app.access.read_apps">>Read your App information</li>
<li v-if="app.access.update_apps">>Update your App information</li>
<li v-if="app.access.read_access">>Read your Access information</li>
<li v-if="app.access.update_access">>Update your Access information</li>
</ul>
</div>
<v-btn color="success" @click="allowAccess()" :disabled="disabledLoginButton" style="width: 100%;">Login to {{ app.name }}</v-btn>
<br><br>
<a :href="app.url">Go to App-Webpage</a>
</v-flex>
</v-layout>
</v-container>
</div>
</template>
<script>
import ServerService from '../services/Server'
import UserService from '../services/User'
import LoginComponent from '../components/Login'
import AppsService from '../services/Apps'
export default {
data () {
return {
nameBig: '',
nameSmall: '',
username: '',
password: '',
errorMessage: '',
app: null,
disabledLoginButton: true,
appId: null
}
},
components: {
'Login': LoginComponent
},
methods: {
getAppData: function () {
AppsService.getAppByKey(this.$route.query.client_id).then((res) => {
this.appId = res.data.data[0].id
AppsService.getAccess(res.data.data[0].id).then((access) => {
if(access.data.data.status == "allowed") {
if(res.data.data[0].properties.stopAutoRedirect) {
this.disabledLoginButton = false;
console.log("Disabled Auto redirect");
} else {
this.allowAccess();
}
console.log("ALLOWED");
} else {
this.disabledLoginButton = false;
}
console.log("Access Data", res.data);
});
console.log("App Data", res.data);
this.app = res.data.data[0];
});
},
allowAccess: function () {
console.log(this.$route.query);
AppsService.allowAccess(this.appId, this.$route.query.redirect_uri, this.$route.query.scope).then((res) => {
console.log("App Access", res);
location.href=res.data.data.redirectUrl
});
}
},
mounted: function() {
this.nameBig = this.$store.getters.getSettingValue("name_big");
this.nameSmall = this.$store.getters.getSettingValue("name_small");
this.getAppData();
}
}
</script>
<style>
.header {
background-image: url('~@/assets/manhattan-407703_1920.jpg');
background-repeat: no-repeat;
margin-top: -100px;
height: 30vh;
text-align: center;
}
.header h1{
padding-top: 200px;
font-size: 56px !important;
font-weight: 400;
line-height: 32px !important;
letter-spacing: normal !important;
}
.header h1 .small{
font-weight: 300 !important;
}
.header h2{
padding-top: 30px;
font-size: 34px !important;
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
h1{
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
h2{
font-weight: 300;
line-height: 32px !important;
letter-spacing: normal !important;
}
</style>

View file

@ -1,6 +1,6 @@
<template> <template>
<div style=""> <div style="">
<div class="header"> <div class="headerStartpage">
<h1>{{ nameBig }}<span class="small">{{ nameSmall }}</span></h1> <h1>{{ nameBig }}<span class="small">{{ nameSmall }}</span></h1>
<h2>{{ slogen }}</h2> <h2>{{ slogen }}</h2>
</div> </div>
@ -154,7 +154,6 @@
</template> </template>
<script> <script>
import ServerService from '../services/Server'
export default { export default {
data () { data () {
return { return {
@ -177,25 +176,24 @@
</script> </script>
<style> <style>
.header { .headerStartpage {
background-image: url('~@/assets/manhattan-407703_1920.jpg'); background-image: url('~@/assets/manhattan-407703_1920.jpg');
background-repeat: no-repeat; background-repeat: no-repeat;
margin-top: -100px; margin-top: -100px;
height: 45vh;
height:90vh; height:90vh;
text-align: center; text-align: center;
} }
.header h1{ .headerStartpage h1{
padding-top: 200px; padding-top: 200px;
font-size: 56px !important; font-size: 56px !important;
font-weight: 400; font-weight: 400;
line-height: 32px !important; line-height: 32px !important;
letter-spacing: normal !important; letter-spacing: normal !important;
} }
.header h1 .small{ .headerStartpage h1 .small{
font-weight: 300 !important; font-weight: 300 !important;
} }
.header h2{ .headerStartpage h2{
padding-top: 30px; padding-top: 30px;
font-size: 34px !important; font-size: 34px !important;
font-weight: 300; font-weight: 300;