admin oauth2 client management
This commit is contained in:
parent
73049447cd
commit
04e0c77a46
@ -143,8 +143,6 @@ const API = {
|
||||
data = dataFilter(data, fields, ['scope', 'verified'])
|
||||
if (!data) throw new Error('Missing fields')
|
||||
|
||||
data.verified = (data.verified != null ? 1 : 0)
|
||||
|
||||
try {
|
||||
await Models.OAuth2Client.query().patchAndFetchById(id, data)
|
||||
await Models.OAuth2AuthorizedClient.query().delete().where('client_id', id)
|
||||
|
@ -2,14 +2,16 @@
|
||||
modal(:show='show', @close='close')
|
||||
.modal-header
|
||||
h3 Ban user
|
||||
.modal-body
|
||||
.modal-body.aligned-form
|
||||
.message.error(v-if='error') {{ error }}
|
||||
input(type='hidden', name='user_id', :value='id')
|
||||
.cell
|
||||
label(for='reason') Reason
|
||||
input#reason(type='text', name='reason', v-model='reason')
|
||||
.cell
|
||||
label(for='expires_at') Expires
|
||||
input#expires_at(type='date', name='expires_at', v-model='expires_at')
|
||||
.modal-footer.text-right
|
||||
.modal-footer.text-align
|
||||
button(@click='submit') Ban
|
||||
button(@click='close') Cancel
|
||||
</template>
|
||||
|
111
src/script/component/ClientModal.vue
Normal file
111
src/script/component/ClientModal.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template lang="pug">
|
||||
modal(:show='show', @close='close')
|
||||
.modal-header
|
||||
h3(v-if="id > 0") Edit Client
|
||||
h3(v-else) New Client
|
||||
.modal-body.aligned-form
|
||||
.message.error(v-if='error') {{ error }}
|
||||
.cell
|
||||
label(for="title") Title
|
||||
input(type="text" id="title" name="title" v-model="title")
|
||||
.cell
|
||||
label(for="description") Description
|
||||
input(type="text" id="description" name="description" v-model="description")
|
||||
.cell
|
||||
label(for="url") URL
|
||||
input(type="text" id="url" name="url" v-model="url")
|
||||
.cell
|
||||
label(for="scope") Scope
|
||||
input(type="text" id="scope" name="scope" v-model="scope")
|
||||
.cell
|
||||
label(for="redirect_url") Redirect
|
||||
input(type="text" id="redirect_url" name="redirect_url" v-model="redirect_url")
|
||||
.cell
|
||||
label(for="verified") Verified
|
||||
input(type="checkbox" id="verified" name="verified" v-model="verified")
|
||||
.modal-footer.text-align
|
||||
button(@click='submit') Done
|
||||
button(@click='newSecret' v-if="id > 0") New Secret
|
||||
button(@click='close') Cancel
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
import Modal from './Modal.vue'
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
||||
|
||||
export default {
|
||||
props: ['show', 'id'],
|
||||
data: function () {
|
||||
return {
|
||||
error: '',
|
||||
title: '',
|
||||
description: '',
|
||||
scope: '',
|
||||
url: '',
|
||||
redirect_url: '',
|
||||
verified: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Modal
|
||||
},
|
||||
methods: {
|
||||
close: function () {
|
||||
this.$emit('close')
|
||||
this.error = ''
|
||||
this.title = ''
|
||||
this.description = ''
|
||||
this.scope = ''
|
||||
this.url = ''
|
||||
this.redirect_url = ''
|
||||
this.verified = false
|
||||
},
|
||||
submit: function () {
|
||||
let url = this.id === -1 ? 'new' : 'update'
|
||||
|
||||
this.$http.post('/admin/api/client/' + url, {
|
||||
id: this.id,
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
scope: this.scope,
|
||||
url: this.url,
|
||||
redirect_url: this.redirect_url,
|
||||
verified: this.verified,
|
||||
csrf: csrfToken
|
||||
}).then(data => {
|
||||
this.close()
|
||||
this.$root.$emit('reload_clients')
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
if (err.body && err.body.error) this.error = err.body.error
|
||||
})
|
||||
},
|
||||
newSecret: function () {
|
||||
this.$http.post('/admin/api/client/new_secret/' + this.id).then(data => {
|
||||
alert('New secret generated.')
|
||||
this.$root.$emit('reload_clients')
|
||||
}).catch(err => {
|
||||
this.error = 'Failed to generate new secret.'
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
id: function () {
|
||||
if (this.id <= 0) return
|
||||
this.$http.get('/admin/api/client/' + this.id).then(data => {
|
||||
let dr = data.body
|
||||
|
||||
this.title = dr.title
|
||||
this.description = dr.description
|
||||
this.scope = dr.scope
|
||||
this.url = dr.url
|
||||
this.redirect_url = dr.redirect_url
|
||||
this.verified = dr.verified
|
||||
}).catch(err => {
|
||||
alert('Failed to fetch client data')
|
||||
this.close()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
85
src/script/component/OAuthClients.vue
Normal file
85
src/script/component/OAuthClients.vue
Normal file
@ -0,0 +1,85 @@
|
||||
<template lang="pug">
|
||||
#clientlist
|
||||
button(@click="editing = -1") New Client
|
||||
.pgn
|
||||
span.pagenum Page {{ pagination.page }} of {{ pagination.pages }}
|
||||
.button(v-if='pagination.page > 1', v-on:click='getClients(pagination.page - 1)') Previous
|
||||
.button(v-for='n in pagination.pages', v-on:click='getClients(n)', v-bind:class='{active: n == pagination.page}') {{ n }}
|
||||
.button(v-if='pagination.page < pagination.pages', v-on:click='getClients(pagination.page + 1)') Next
|
||||
.list.client
|
||||
.message.error(v-if="error") {{ error }}
|
||||
.application.list-item(v-else v-for="client in clients")
|
||||
.picture
|
||||
img(v-if="client.icon" :src="'/usercontent/images/' + client.icon")
|
||||
.noicon(v-else)
|
||||
i.fa.fa-fw.fa-gears
|
||||
.info
|
||||
.stamps
|
||||
.verified(v-if="client.verified")
|
||||
i.fa.fa-fw.fa-check
|
||||
.name {{ client.title }}
|
||||
.description {{ client.description }}
|
||||
a.url(:href='client.url', target='_blank', rel='nofollow') {{ client.url }}
|
||||
.scope Scopes: {{ client.scope }}
|
||||
.redirect_url Redirect: {{ client.redirect_url }}
|
||||
.id Client ID: {{ client.id }}
|
||||
.secret
|
||||
| Client Secret:
|
||||
#showbutton Hover
|
||||
#hiddensecret {{ client.secret }}
|
||||
.button.edit(@click="editing = client.id") Edit
|
||||
.button.delete(@click="deleteClient(client.id)") Delete
|
||||
client-modal(:show="editing != 0" @close='editing = 0', :id='editing')
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
import ClientModal from './ClientModal.vue'
|
||||
|
||||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
clients: [],
|
||||
pagination: {
|
||||
offset: 0,
|
||||
page: 1,
|
||||
pages: 1,
|
||||
perPage: 6,
|
||||
total: 0
|
||||
},
|
||||
editing: 0,
|
||||
error: ''
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ClientModal
|
||||
},
|
||||
methods: {
|
||||
getClients: function (page) {
|
||||
this.pagination.total = 0
|
||||
this.error = ''
|
||||
|
||||
this.$http.get('/admin/api/clients?page=' + page).then(data => {
|
||||
if (data.body && data.body.error) {
|
||||
this.error = data.body.error
|
||||
return
|
||||
}
|
||||
|
||||
this.pagination = data.body.page
|
||||
this.clients = data.body.clients
|
||||
})
|
||||
},
|
||||
deleteClient: function (id) {
|
||||
this.$http.post('/admin/api/client/delete/' + id).then(data => {
|
||||
this.getClients(1)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.getClients(1)
|
||||
|
||||
this.$root.$on('reload_clients', () => {
|
||||
this.getClients(1)
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,8 +1,20 @@
|
||||
<template lang="pug">
|
||||
.root
|
||||
h1 Manage OAuth2 Clients
|
||||
o-auth-clients
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {}
|
||||
import OAuthClients from '../component/OAuthClients.vue'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
newClient: function () {
|
||||
alert('not yet')
|
||||
}
|
||||
},
|
||||
components: {
|
||||
OAuthClients
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -10,6 +10,7 @@
|
||||
<script type="text/javascript">
|
||||
import UserList from '../component/UserList.vue'
|
||||
import BanList from '../component/BanList.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UserList, BanList
|
||||
|
@ -71,11 +71,22 @@ nav
|
||||
background-color: #fff
|
||||
|
||||
.application
|
||||
height: 200px
|
||||
min-height: 200px
|
||||
|
||||
#hiddensecret
|
||||
display: none
|
||||
&.shown
|
||||
color: #ff796f
|
||||
background-color: #f1f1f1
|
||||
padding: 5px
|
||||
min-width: 250px
|
||||
|
||||
#showbutton
|
||||
font-style: italic
|
||||
display: inline-block
|
||||
cursor: pointer
|
||||
&:hover > #hiddensecret
|
||||
display: block
|
||||
|
||||
.link
|
||||
color: green
|
||||
cursor: pointer
|
||||
@ -97,7 +108,7 @@ nav
|
||||
vertical-align: middle
|
||||
|
||||
.modal-container
|
||||
width: 300px
|
||||
width: 360px
|
||||
margin: 0px auto
|
||||
padding: 20px 30px
|
||||
background-color: #fff
|
||||
@ -113,8 +124,15 @@ nav
|
||||
.modal-body
|
||||
margin: 20px 0
|
||||
|
||||
.modal-default-button
|
||||
float: right
|
||||
.modal-footer
|
||||
min-height: 50px
|
||||
|
||||
button
|
||||
margin: 5px
|
||||
display: inline-block
|
||||
|
||||
&.text-align
|
||||
text-align: center
|
||||
|
||||
/*
|
||||
* The following styles are auto-applied to elements with
|
||||
@ -125,6 +143,16 @@ nav
|
||||
* these styles.
|
||||
*/
|
||||
|
||||
.fade-enter-active, .fade-leave-active
|
||||
transition-property: opacity
|
||||
transition-duration: .25s
|
||||
|
||||
.fade-enter-active
|
||||
transition-delay: .25s
|
||||
|
||||
.fade-enter, .fade-leave-active
|
||||
opacity: 0
|
||||
|
||||
.modal-enter
|
||||
opacity: 0
|
||||
|
||||
@ -135,9 +163,6 @@ nav
|
||||
-webkit-transform: scale(1.1)
|
||||
transform: scale(1.1)
|
||||
|
||||
.modal-footer
|
||||
min-height: 50px
|
||||
|
||||
form
|
||||
.message
|
||||
display: none
|
||||
|
@ -211,6 +211,7 @@ button, .button, input[type="submit"]
|
||||
|
||||
.button
|
||||
display: inline-block
|
||||
margin-right: 5px
|
||||
|
||||
.boxcont
|
||||
.box
|
||||
@ -568,6 +569,17 @@ select
|
||||
margin-left: 5px
|
||||
border-radius: 5px
|
||||
|
||||
.aligned-form
|
||||
.cell
|
||||
margin-top: 10px
|
||||
label
|
||||
width: 120px
|
||||
float: left
|
||||
margin: 0
|
||||
padding: 8px 0
|
||||
input[type="checkbox"]
|
||||
margin-top: 10px
|
||||
|
||||
@media all and (max-width: 800px)
|
||||
.navigator
|
||||
padding: 0 10px
|
||||
|
@ -3,8 +3,6 @@ extends layout.pug
|
||||
block body
|
||||
.container
|
||||
.content
|
||||
transition(name="fade")
|
||||
router-view
|
||||
|
||||
.templates
|
||||
script(type="text/x-template" id="ban-modal-template").
|
||||
|
||||
|
Reference in New Issue
Block a user