diff --git a/server/api/admin.js b/server/api/admin.js
index 79f8b80..c2aa95f 100644
--- a/server/api/admin.js
+++ b/server/api/admin.js
@@ -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)
diff --git a/src/script/component/BanModal.vue b/src/script/component/BanModal.vue
index a55a98d..8d177d1 100644
--- a/src/script/component/BanModal.vue
+++ b/src/script/component/BanModal.vue
@@ -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')
- label(for='reason') Reason
- input#reason(type='text', name='reason', v-model='reason')
- label(for='expires_at') Expires
- input#expires_at(type='date', name='expires_at', v-model='expires_at')
- .modal-footer.text-right
+ .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-align
button(@click='submit') Ban
button(@click='close') Cancel
diff --git a/src/script/component/ClientModal.vue b/src/script/component/ClientModal.vue
new file mode 100644
index 0000000..0110b9e
--- /dev/null
+++ b/src/script/component/ClientModal.vue
@@ -0,0 +1,111 @@
+
+ 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
+
+
+
diff --git a/src/script/component/OAuthClients.vue b/src/script/component/OAuthClients.vue
new file mode 100644
index 0000000..4f0a376
--- /dev/null
+++ b/src/script/component/OAuthClients.vue
@@ -0,0 +1,85 @@
+
+ #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')
+
+
+
diff --git a/src/script/views/OAuth2.vue b/src/script/views/OAuth2.vue
index 2620217..729290c 100644
--- a/src/script/views/OAuth2.vue
+++ b/src/script/views/OAuth2.vue
@@ -1,8 +1,20 @@
- .root
- h1 Manage OAuth2 Clients
+ .root
+ h1 Manage OAuth2 Clients
+ o-auth-clients
diff --git a/src/script/views/Users.vue b/src/script/views/Users.vue
index 3b22f64..11ce729 100644
--- a/src/script/views/Users.vue
+++ b/src/script/views/Users.vue
@@ -10,6 +10,7 @@