Created hidden Admin Panel
This commit is contained in:
parent
bcd2beb980
commit
eb95d308f9
@ -8,7 +8,7 @@ export const set_role = (
|
|||||||
user: number,
|
user: number,
|
||||||
role: UserRole,
|
role: UserRole,
|
||||||
token: string
|
token: string
|
||||||
): Promise<Responses.Admin.SetUserRole> =>
|
): Promise<Responses.Admin.SetUserRole | Responses.ErrorResponse> =>
|
||||||
post_token<Requests.Admin.SetUserRole>(
|
post_token<Requests.Admin.SetUserRole>(
|
||||||
'/api/admin/set_role',
|
'/api/admin/set_role',
|
||||||
{
|
{
|
||||||
@ -21,7 +21,7 @@ export const set_role = (
|
|||||||
export const logout = (
|
export const logout = (
|
||||||
user: number,
|
user: number,
|
||||||
token: string
|
token: string
|
||||||
): Promise<Responses.Admin.LogoutAllUser> =>
|
): Promise<Responses.Admin.LogoutAllUser | Responses.ErrorResponse> =>
|
||||||
post_token<Requests.Admin.LogoutAll>(
|
post_token<Requests.Admin.LogoutAll>(
|
||||||
'/api/admin/logout',
|
'/api/admin/logout',
|
||||||
{
|
{
|
||||||
@ -33,7 +33,7 @@ export const logout = (
|
|||||||
export const delete_user = (
|
export const delete_user = (
|
||||||
user: number,
|
user: number,
|
||||||
token: string
|
token: string
|
||||||
): Promise<Responses.Admin.DeleteUser> =>
|
): Promise<Responses.Admin.DeleteUser | Responses.ErrorResponse> =>
|
||||||
post_token<Requests.Admin.DeleteUser>(
|
post_token<Requests.Admin.DeleteUser>(
|
||||||
'/api/admin/delete',
|
'/api/admin/delete',
|
||||||
{
|
{
|
||||||
@ -45,7 +45,7 @@ export const delete_user = (
|
|||||||
export const disable_tfa = (
|
export const disable_tfa = (
|
||||||
user: number,
|
user: number,
|
||||||
token: string
|
token: string
|
||||||
): Promise<Responses.Admin.DisableTfa> =>
|
): Promise<Responses.Admin.DisableTfa | Responses.ErrorResponse> =>
|
||||||
post_token<Requests.Admin.DisableTfa>(
|
post_token<Requests.Admin.DisableTfa>(
|
||||||
'/api/admin/disable_2fa',
|
'/api/admin/disable_2fa',
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ import FSView from '@/views/FSView.vue';
|
|||||||
import SetTokenView from '@/views/SetTokenView.vue';
|
import SetTokenView from '@/views/SetTokenView.vue';
|
||||||
import ProfileView from '@/views/ProfileView.vue';
|
import ProfileView from '@/views/ProfileView.vue';
|
||||||
import TFAView from '@/views/TFAView.vue';
|
import TFAView from '@/views/TFAView.vue';
|
||||||
|
import AdminView from '@/views/AdminView.vue';
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
@ -24,6 +25,10 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: '2fa',
|
name: '2fa',
|
||||||
component: TFAView
|
component: TFAView
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/admin',
|
||||||
|
component: AdminView
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
component: AboutView
|
component: AboutView
|
||||||
|
109
frontend/src/views/AdminView.vue
Normal file
109
frontend/src/views/AdminView.vue
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { inject, onBeforeMount, ref } from 'vue';
|
||||||
|
import {
|
||||||
|
Responses,
|
||||||
|
check_token,
|
||||||
|
TokenInjectType,
|
||||||
|
Admin,
|
||||||
|
isErrorResponse
|
||||||
|
} from '@/api';
|
||||||
|
import { onBeforeRouteUpdate } from 'vue-router';
|
||||||
|
import router from '@/router';
|
||||||
|
|
||||||
|
const jwt = inject<TokenInjectType>('jwt') as TokenInjectType;
|
||||||
|
|
||||||
|
const users = ref<Responses.Admin.GetUsersEntry[]>([]);
|
||||||
|
|
||||||
|
onBeforeRouteUpdate(async () => {
|
||||||
|
await updatePanel();
|
||||||
|
});
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
await updatePanel();
|
||||||
|
});
|
||||||
|
async function updatePanel() {
|
||||||
|
const token = await check_token(jwt);
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
|
const res = await Admin.get_users(token);
|
||||||
|
if (isErrorResponse(res)) return router.replace({ path: '/' });
|
||||||
|
users.value = res.users;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setRole(user: number, roleStr: string) {
|
||||||
|
const token = await check_token(jwt);
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
|
const res = await Admin.set_role(user, parseInt(roleStr, 10), token);
|
||||||
|
if (isErrorResponse(res)) console.error(res.message);
|
||||||
|
await updatePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function disableTfa(user: number) {
|
||||||
|
const token = await check_token(jwt);
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
|
const res = await Admin.disable_tfa(user, token);
|
||||||
|
if (isErrorResponse(res)) console.error(res.message);
|
||||||
|
await updatePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function logoutUser(user: number) {
|
||||||
|
const token = await check_token(jwt);
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
|
const res = await Admin.logout(user, token);
|
||||||
|
if (isErrorResponse(res)) console.error(res.message);
|
||||||
|
await updatePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteUser(user: number) {
|
||||||
|
const token = await check_token(jwt);
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
|
const res = await Admin.delete_user(user, token);
|
||||||
|
if (isErrorResponse(res)) console.error(res.message);
|
||||||
|
await updatePanel();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Role</th>
|
||||||
|
<th>Tfa Status</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="user in users" :key="user.id">
|
||||||
|
<td>{{ user.name }}</td>
|
||||||
|
<td>{{ user.gitlab ? 'Gitlab' : 'Password' }}</td>
|
||||||
|
<td>
|
||||||
|
<select @change="setRole(user.id, $event.target.value)">
|
||||||
|
<option value="0" :selected="user.role === 0 ? true : null">
|
||||||
|
Disabled
|
||||||
|
</option>
|
||||||
|
<option value="1" :selected="user.role === 1 ? true : null">
|
||||||
|
User
|
||||||
|
</option>
|
||||||
|
<option value="2" :selected="user.role === 2 ? true : null">
|
||||||
|
Admin
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td v-if="user.gitlab"></td>
|
||||||
|
<td v-else>
|
||||||
|
{{ user.tfaEnabled ? 'Enabled' : 'Disabled' }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button v-if="user.tfaEnabled" @click="disableTfa(user.id)">
|
||||||
|
Disable Tfa
|
||||||
|
</button>
|
||||||
|
<button @click="logoutUser(user.id)">Logout all</button>
|
||||||
|
<button @click="deleteUser(user.id)">Delete</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -10,22 +10,16 @@ import {
|
|||||||
import { AuthService } from 'services/auth';
|
import { AuthService } from 'services/auth';
|
||||||
import { Requests, Responses, UserRole } from 'dto';
|
import { Requests, Responses, UserRole } from 'dto';
|
||||||
import { Role } from 'authguards';
|
import { Role } from 'authguards';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { tfaTypes } from 'entities';
|
||||||
import { tfaTypes, User } from 'entities';
|
|
||||||
import { Repository } from 'typeorm';
|
|
||||||
|
|
||||||
@Controller('api/admin')
|
@Controller('api/admin')
|
||||||
export default class AdminController {
|
export default class AdminController {
|
||||||
constructor(
|
constructor(private authService: AuthService) {}
|
||||||
@InjectRepository(User)
|
|
||||||
private userRepo: Repository<User>,
|
|
||||||
private authService: AuthService
|
|
||||||
) {}
|
|
||||||
|
|
||||||
@Role(UserRole.ADMIN)
|
@Role(UserRole.ADMIN)
|
||||||
@Get('users')
|
@Get('users')
|
||||||
async getUsers(): Promise<Responses.Admin.GetUsers> {
|
async getUsers(): Promise<Responses.Admin.GetUsers> {
|
||||||
const users = await this.userRepo.find();
|
const users = await this.authService.getUsers();
|
||||||
const entries = users.map(
|
const entries = users.map(
|
||||||
(user) =>
|
(user) =>
|
||||||
new Responses.Admin.GetUsersEntry(
|
new Responses.Admin.GetUsersEntry(
|
||||||
|
@ -30,6 +30,10 @@ export default class BaseAuthService {
|
|||||||
protected fsService: FileSystemService
|
protected fsService: FileSystemService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
getUsers(): Promise<User[]> {
|
||||||
|
return this.userRepo.find();
|
||||||
|
}
|
||||||
|
|
||||||
async getUser(userId: number): Promise<User | null> {
|
async getUser(userId: number): Promise<User | null> {
|
||||||
return this.userRepo.findOneBy({
|
return this.userRepo.findOneBy({
|
||||||
id: userId
|
id: userId
|
||||||
|
Loading…
Reference in New Issue
Block a user