User management

This commit is contained in:
Pitu 2019-02-26 23:13:24 +09:00
parent 62c0c1db20
commit 7a74647d3e
6 changed files with 332 additions and 13 deletions

View File

@ -2,13 +2,13 @@ const Route = require('../../structures/Route');
class userDemote extends Route {
constructor() {
super('/admin/users/demote', 'get', { adminOnly: true });
super('/admin/users/demote', 'post', { adminOnly: true });
}
async run(req, res, db) {
if (!req.body) return res.status(400).json({ message: 'No body provided' });
const { id } = req.body;
if (!id) return res.status(400).json({ message: 'No name provided' });
if (!id) return res.status(400).json({ message: 'No id provided' });
try {
await db.table('users')
@ -19,7 +19,7 @@ class userDemote extends Route {
}
return res.json({
message: 'Successfully promoted user'
message: 'Successfully demoted user'
});
}
}

View File

@ -0,0 +1,27 @@
const Route = require('../../structures/Route');
class userDisable extends Route {
constructor() {
super('/admin/users/disable', 'post', { adminOnly: true });
}
async run(req, res, db) {
if (!req.body) return res.status(400).json({ message: 'No body provided' });
const { id } = req.body;
if (!id) return res.status(400).json({ message: 'No id provided' });
try {
await db.table('users')
.where({ id })
.update({ enabled: false });
} catch (error) {
return super.error(res, error);
}
return res.json({
message: 'Successfully disabled user'
});
}
}
module.exports = userDisable;

View File

@ -0,0 +1,27 @@
const Route = require('../../structures/Route');
class userEnable extends Route {
constructor() {
super('/admin/users/enable', 'post', { adminOnly: true });
}
async run(req, res, db) {
if (!req.body) return res.status(400).json({ message: 'No body provided' });
const { id } = req.body;
if (!id) return res.status(400).json({ message: 'No id provided' });
try {
await db.table('users')
.where({ id })
.update({ enabled: true });
} catch (error) {
return super.error(res, error);
}
return res.json({
message: 'Successfully enabled user'
});
}
}
module.exports = userEnable;

View File

@ -2,13 +2,13 @@ const Route = require('../../structures/Route');
class userPromote extends Route {
constructor() {
super('/admin/users/promote', 'get', { adminOnly: true });
super('/admin/users/promote', 'post', { adminOnly: true });
}
async run(req, res, db) {
if (!req.body) return res.status(400).json({ message: 'No body provided' });
const { id } = req.body;
if (!id) return res.status(400).json({ message: 'No name provided' });
if (!id) return res.status(400).json({ message: 'No id provided' });
try {
await db.table('users')

View File

@ -44,15 +44,23 @@
<router-link to="/dashboard/account">
<i class="icon-ecommerce-tag-c" />Account
</router-link>
<hr>
<router-link to="/dashboard/users">
<i class="icon-setting-gear-a" />Users
</router-link>
<router-link to="/dashboard/settings">
<i class="icon-setting-gear-a" />Settings
</router-link>
<template v-if="user.isAdmin">
<hr>
<router-link to="/dashboard/users">
<i class="icon-setting-gear-a" />Users
</router-link>
<router-link to="/dashboard/settings">
<i class="icon-setting-gear-a" />Settings
</router-link>
</template>
</div>
</template>
<script>
export default {};
export default {
computed: {
user() {
return this.$store.state.user;
}
},
};
</script>

View File

@ -0,0 +1,257 @@
<style lang="scss" scoped>
@import '~/assets/styles/_colors.scss';
section { background-color: $backgroundLight1 !important; }
section.hero div.hero-body {
align-items: baseline;
}
div.search-container {
display: flex;
justify-content: center;
}
div.view-container {
padding: 2rem;
}
div.album {
display: flex;
flex-wrap: wrap;
margin-bottom: 10px;
div.arrow-container {
width: 2em;
height: 64px;
position: relative;
cursor: pointer;
i {
border: 2px solid $defaultTextColor;
border-right: 0;
border-top: 0;
display: block;
height: 1em;
position: absolute;
transform: rotate(-135deg);
transform-origin: center;
width: 1em;
z-index: 4;
top: 22px;
-webkit-transition: transform 0.1s linear;
-moz-transition: transform 0.1s linear;
-ms-transition: transform 0.1s linear;
-o-transition: transform 0.1s linear;
transition: transform 0.1s linear;
&.active {
transform: rotate(-45deg);
}
}
}
div.thumb {
width: 64px;
height: 64px;
-webkit-box-shadow: $boxShadowLight;
box-shadow: $boxShadowLight;
}
div.info {
margin-left: 15px;
h4 {
font-size: 1.5rem;
a {
color: $defaultTextColor;
font-weight: 400;
&:hover { text-decoration: underline; }
}
}
span { display: block; }
span:nth-child(3) {
font-size: 0.9rem;
}
}
div.latest {
flex-grow: 1;
justify-content: flex-end;
display: flex;
margin-left: 15px;
span.no-files {
font-size: 1.5em;
color: #b1b1b1;
padding-top: 17px;
}
div.more {
width: 64px;
height: 64px;
background: white;
display: flex;
align-items: center;
padding: 10px;
text-align: center;
a {
line-height: 1rem;
color: $defaultTextColor;
&:hover { text-decoration: underline; }
}
}
}
div.details {
flex: 0 1 100%;
padding-left: 2em;
padding-top: 1em;
min-height: 50px;
.b-table {
padding: 2em 0em;
.table-wrapper {
-webkit-box-shadow: $boxShadowLight;
box-shadow: $boxShadowLight;
}
}
}
}
div.column > h2.subtitle { padding-top: 1px; }
</style>
<style lang="scss">
@import '~/assets/styles/_colors.scss';
.b-table {
.table-wrapper {
-webkit-box-shadow: $boxShadowLight;
box-shadow: $boxShadowLight;
}
}
</style>
<template>
<section class="hero is-fullheight">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-narrow">
<Sidebar />
</div>
<div class="column">
<h2 class="subtitle">Manage your users</h2>
<hr>
<div class="view-container">
<b-table
:data="users || []"
:mobile-cards="true">
<template slot-scope="props">
<b-table-column field="id"
label="Id"
centered>
{{ props.row.id }}
</b-table-column>
<b-table-column field="username"
label="Username"
centered>
{{ props.row.username }}
</b-table-column>
<b-table-column field="enabled"
label="Enabled"
centered>
<b-switch v-model="props.row.enabled"
@input="changeEnabledStatus(props.row)" />
</b-table-column>
<b-table-column field="isAdmin"
label="Admin"
centered>
<b-switch v-model="props.row.isAdmin"
@input="changeIsAdmin(props.row)" />
</b-table-column>
</template>
<template slot="empty">
<div class="has-text-centered">
<i class="icon-misc-mood-sad" />
</div>
<div class="has-text-centered">
Nothing here
</div>
</template>
<template slot="footer">
<div class="has-text-right">
{{ users.length }} users
</div>
</template>
</b-table>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
import Sidebar from '../../components/sidebar/Sidebar.vue';
export default {
components: {
Sidebar
},
data() {
return {
users: []
};
},
computed: {
config() {
return this.$store.state.config;
}
},
metaInfo() {
return { title: 'Uploads' };
},
mounted() {
this.getUsers();
this.$ga.page({
page: '/dashboard/users',
title: 'Users',
location: window.location.href
});
},
methods: {
async getUsers() {
try {
const response = await this.axios.get(`${this.config.baseURL}/admin/users`);
this.users = response.data.users;
console.log(this.users);
} catch (error) {
console.error(error);
}
},
async changeEnabledStatus(row) {
try {
const response = await this.axios.post(`${this.config.baseURL}/admin/users/${row.enabled ? 'enable' : 'disable'}`, {
id: row.id
});
this.$toast.open(response.data.message);
} catch (error) {
console.error(error);
}
},
async changeIsAdmin(row) {
try {
const response = await this.axios.post(`${this.config.baseURL}/admin/users/${row.isAdmin ? 'promote' : 'demote'}`, {
id: row.id
});
this.$toast.open(response.data.message);
} catch (error) {
console.error(error);
}
}
}
};
</script>