This commit is contained in:
Aru Moon 2022-01-17 18:08:53 +01:00 committed by GitHub
commit c874dee383
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 181 additions and 16 deletions

View File

@ -1,3 +1,4 @@
const { response } = require('express');
const Route = require('../../structures/Route');
const Util = require('../../utils/Util');
@ -11,21 +12,26 @@ class filesGET extends Route {
if (!id) return res.status(400).json({ message: 'Invalid file ID supplied' });
let file = await db.table('files').where({ id }).first();
const user = await db.table('users')
.select('id', 'username', 'enabled', 'createdAt', 'editedAt', 'apiKeyEditedAt', 'isAdmin')
.where({ id: file.userId })
.first();
file = Util.constructFilePublicLink(req, file);
// Additional relevant data
const filesFromUser = await db.table('files').where({ userId: user.id }).select('id');
user.fileCount = filesFromUser.length;
if (file.userId) {
const user = await db.table('users')
.select('id', 'username', 'enabled', 'createdAt', 'editedAt', 'apiKeyEditedAt', 'isAdmin')
.where({ id: file.userId })
.first();
const filesFromUser = await db.table('files').where({ userId: user.id }).select('id');
user.fileCount = filesFromUser.length;
return res.json({
return res.json({
message: 'Successfully retrieved file',
file,
user
})
}
else return res.json({
message: 'Successfully retrieved file',
file,
user
});
file
})
}
}

View File

@ -0,0 +1,46 @@
const Route = require('../../structures/Route');
const Util = require('../../utils/Util');
class filesGET extends Route {
constructor() {
super('/admin/uploads', 'get', { adminOnly: true });
}
async run(req, res, db) {
try {
let count = 0;
let files = db.table('files')
.where({ userId: null })
.orderBy('id', 'desc');
const { page, limit = 100 } = req.query;
if (page && page >= 0) {
files = await files.offset((page - 1) * limit).limit(limit);
const dbRes = await db.table('files')
.count('* as count')
.where({ userId: null })
.first();
count = dbRes.count;
} else {
files = await files; // execute the query
count = files.length;
}
for (let file of files) {
file = Util.constructFilePublicLink(req, file);
}
return res.json({
message: 'Successfully retrieved uploads',
files,
count
});
} catch (error) {
return super.error(res, error);
}
}
}
module.exports = filesGET;

View File

@ -9,7 +9,7 @@ class userDemote extends Route {
async run(req, res) {
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' });
// if (!id) return res.status(400).json({ message: 'No id provided' });
try {
await Util.deleteAllFilesFromUser(id);
@ -18,7 +18,7 @@ class userDemote extends Route {
}
return res.json({
message: 'Successfully deleted the user\'s files'
message: 'Successfully deleted files'
});
}
}

View File

@ -27,6 +27,7 @@
Administration
<b-icon class="is-pulled-right" :icon="props.expanded ? 'menu-down' : 'menu-up'" />
</template>
<b-menu-item icon="file-cog" label="Public uploads" tag="nuxt-link" to="/dashboard/admin/uploads" exact />
<b-menu-item icon="account" label="Users" tag="nuxt-link" to="/dashboard/admin/users" exact />
<b-menu-item icon="cog-outline" label="Settings" tag="nuxt-link" to="/dashboard/admin/settings" exact />
<b-menu-item icon="chart-line" label="Statistics" tag="nuxt-link" to="/dashboard/admin/statistics" exact />

View File

@ -66,7 +66,7 @@
<span><timeago :since="admin.file.createdAt" /></span>
</b-field>
</div>
<div class="column is-6">
<div class="column is-6" v-if="admin.file.userId">
<b-field
label="User Id"
horizontal>
@ -103,13 +103,13 @@
<div class="mb2 mt2 text-center">
<b-button
v-if="admin.user.id !== auth.user.id"
v-if="admin.file.userId !== auth.user.id"
type="is-danger"
@click="promptBanIP">
Ban IP
</b-button>
<b-button
v-if="admin.user.id !== auth.user.id"
v-if="admin.user.id !== auth.user.id && admin.file.userId"
type="is-danger"
@click="promptDisableUser">
Disable user

View File

@ -0,0 +1,103 @@
<style lang="scss" scoped>
.underline { text-decoration: underline; }
</style>
<template>
<section class="section is-fullheight dashboard">
<div class="container">
<div class="columns">
<div class="column is-narrow">
<Sidebar />
</div>
<div class="column">
<h2 class="subtitle">
Manage public uploads
</h2>
<hr>
<div class="mb2 mt2 text-center">
<b-button
type="is-danger"
@click="promptPurgeFiles()">
Purge files
</b-button>
</div>
<Grid
v-if="user.files.length"
:files="user.files">
<template v-slot:pagination>
<b-pagination
:total="user.totalFiles"
:per-page="limit"
:current.sync="current"
range-before="2"
range-after="2"
class="pagination-slot"
icon-prev="icon-interface-arrow-left"
icon-next="icon-interface-arrow-right"
icon-pack="icon"
aria-next-label="Next page"
aria-previous-label="Previous page"
aria-page-label="Page"
aria-current-label="Current page" />
</template>
</Grid>
</div>
</div>
</div>
</section>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
import Sidebar from '~/components/sidebar/Sidebar.vue';
import Grid from '~/components/grid/Grid.vue';
export default {
components: {
Sidebar,
Grid
},
middleware: ['auth', 'admin'],
data() {
return {
options: {},
current: 1,
isLoading: false
};
},
computed: {
...mapGetters({
limit: 'images/getLimit'
}),
...mapState({
user: state => state.admin.user
})
},
watch: {
current: 'fetchPaginate'
},
async asyncData({ app, params }) {
await app.store.dispatch('admin/fetchFiles');
},
methods: {
...mapActions({
fetch: 'admin/fetchFiles'
}),
async fetchPaginate() {
this.isLoading = true;
await this.fetch( this.current );
this.isLoading = false;
},
promptPurgeFiles() {
this.$buefy.dialog.confirm({
message: 'Are you sure you want to delete public files?',
onConfirm: () => this.purgeFiles()
});
},
async purgeFiles() {
this.$handler.executeAction('admin/purgeUserFiles', null);
}
}
};
</script>

View File

@ -1,3 +1,5 @@
import axios from "axios";
export const state = () => ({
users: [],
user: {
@ -57,6 +59,13 @@ export const actions = {
return response;
},
async fetchFiles({ commit }, page) {
page = page || 1;
const response = await this.$axios.$get('admin/uploads', { params: {limit: 50, page} });
commit('setUserInfo', { ...response, page });
return response;
},
async fetchFile({ commit }, id) {
const response = await this.$axios.$get(`admin/file/${id}`);
commit('setFile', response);