mirror of
https://github.com/HangarMC/Hangar.git
synced 2024-12-21 06:51:19 +08:00
Add role change form to admin settings page
This commit is contained in:
parent
586ef6e707
commit
8e75016312
@ -11,6 +11,7 @@ import io.papermc.hangar.controller.extras.pagination.filters.log.LogProjectFilt
|
||||
import io.papermc.hangar.controller.extras.pagination.filters.log.LogSubjectFilter;
|
||||
import io.papermc.hangar.controller.extras.pagination.filters.log.LogUserFilter;
|
||||
import io.papermc.hangar.controller.extras.pagination.filters.log.LogVersionFilter;
|
||||
import io.papermc.hangar.db.dao.internal.table.roles.RolesDAO;
|
||||
import io.papermc.hangar.model.api.PaginatedResult;
|
||||
import io.papermc.hangar.model.api.requests.RequestPagination;
|
||||
import io.papermc.hangar.model.common.NamedPermission;
|
||||
@ -18,10 +19,12 @@ import io.papermc.hangar.model.common.roles.GlobalRole;
|
||||
import io.papermc.hangar.model.db.JobTable;
|
||||
import io.papermc.hangar.model.db.UserTable;
|
||||
import io.papermc.hangar.model.db.roles.GlobalRoleTable;
|
||||
import io.papermc.hangar.model.db.roles.RoleTable;
|
||||
import io.papermc.hangar.model.internal.admin.health.MissingFileCheck;
|
||||
import io.papermc.hangar.model.internal.admin.health.UnhealthyProject;
|
||||
import io.papermc.hangar.model.internal.api.requests.StringContent;
|
||||
import io.papermc.hangar.model.internal.api.requests.admin.ChangePlatformVersionsForm;
|
||||
import io.papermc.hangar.model.internal.api.requests.admin.ChangeRoleForm;
|
||||
import io.papermc.hangar.model.internal.api.responses.HealthReport;
|
||||
import io.papermc.hangar.model.internal.logs.HangarLoggedAction;
|
||||
import io.papermc.hangar.security.annotations.permission.PermissionRequired;
|
||||
@ -42,6 +45,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@ -65,9 +69,10 @@ public class AdminController extends HangarComponent {
|
||||
private final UserService userService;
|
||||
private final ObjectMapper mapper;
|
||||
private final GlobalRoleService globalRoleService;
|
||||
private final RolesDAO rolesDAO;
|
||||
|
||||
@Autowired
|
||||
public AdminController(final PlatformService platformService, final StatService statService, final HealthService healthService, final JobService jobService, final UserService userService, final ObjectMapper mapper, final GlobalRoleService globalRoleService) {
|
||||
public AdminController(final PlatformService platformService, final StatService statService, final HealthService healthService, final JobService jobService, final UserService userService, final ObjectMapper mapper, final GlobalRoleService globalRoleService, final RolesDAO rolesDAO) {
|
||||
this.platformService = platformService;
|
||||
this.statService = statService;
|
||||
this.healthService = healthService;
|
||||
@ -75,6 +80,7 @@ public class AdminController extends HangarComponent {
|
||||
this.userService = userService;
|
||||
this.mapper = mapper;
|
||||
this.globalRoleService = globalRoleService;
|
||||
this.rolesDAO = rolesDAO;
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ -84,6 +90,17 @@ public class AdminController extends HangarComponent {
|
||||
this.platformService.updatePlatformVersions(form);
|
||||
}
|
||||
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PostMapping(path = "/roles", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
@PermissionRequired(NamedPermission.MANUAL_VALUE_CHANGES)
|
||||
@Transactional
|
||||
public void changeRoles(@RequestBody final List<@Valid ChangeRoleForm> roles) {
|
||||
for (final ChangeRoleForm role : roles) {
|
||||
System.out.println(role.roleId());
|
||||
this.rolesDAO.update(role.roleId(), role.title(), role.color(), role.rank());
|
||||
}
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@PermissionRequired(NamedPermission.VIEW_STATS)
|
||||
@GetMapping(path = "/stats", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.papermc.hangar.db.dao.internal.table.roles;
|
||||
|
||||
import io.papermc.hangar.model.db.roles.RoleTable;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper;
|
||||
import org.jdbi.v3.sqlobject.customizer.BindBean;
|
||||
import org.jdbi.v3.sqlobject.customizer.Timestamped;
|
||||
@ -16,6 +17,9 @@ public interface RolesDAO {
|
||||
@SqlUpdate("INSERT INTO roles VALUES (:id, :now, :name, :category, :title, :color, :assignable, :rank, cast(:permission AS bit(64)))")
|
||||
void insert(@BindBean RoleTable roleTable);
|
||||
|
||||
@SqlUpdate("UPDATE roles VALUES SET title = :title, color = :color, rank = :rank WHERE id = :id")
|
||||
void update(long id, String title, String color, @Nullable Integer rank);
|
||||
|
||||
@SqlQuery("SELECT id, created_at, name, category, title, color, assignable, rank, permission::bigint FROM roles WHERE id = :id")
|
||||
RoleTable getById(long id);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class RoleTable extends Table implements Named {
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
private RoleTable(final long id, final String name, final RoleCategory category, final String title, final String color, final boolean assignable, final Integer rank, final Permission permission) {
|
||||
public RoleTable(final long id, final String name, final RoleCategory category, final String title, final String color, final boolean assignable, final Integer rank, final Permission permission) {
|
||||
super(id);
|
||||
this.name = name;
|
||||
this.category = category;
|
||||
|
@ -0,0 +1,7 @@
|
||||
package io.papermc.hangar.model.internal.api.requests.admin;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record ChangeRoleForm(long roleId, @NotBlank String title, @NotBlank String color, @Nullable Integer rank) {
|
||||
}
|
@ -5,11 +5,13 @@ import io.papermc.hangar.model.common.roles.GlobalRole;
|
||||
import io.papermc.hangar.model.db.roles.GlobalRoleTable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class GlobalRoleService extends RoleService<GlobalRoleTable, GlobalRole, GlobalRolesDAO> {
|
||||
|
||||
@Autowired
|
||||
public GlobalRoleService(final GlobalRolesDAO roleDao) {
|
||||
super(roleDao);
|
||||
}
|
||||
|
@ -341,8 +341,8 @@ function isRecent(date: string): boolean {
|
||||
<DropdownItem v-if="hasPerms(NamedPermission.VIEW_STATS)" to="/admin/stats">{{ t("nav.user.stats") }}</DropdownItem>
|
||||
<DropdownItem v-if="hasPerms(NamedPermission.VIEW_HEALTH)" to="/admin/health">{{ t("nav.user.health") }}</DropdownItem>
|
||||
<DropdownItem v-if="hasPerms(NamedPermission.VIEW_LOGS)" to="/admin/log">{{ t("nav.user.log") }}</DropdownItem>
|
||||
<DropdownItem v-if="hasPerms(NamedPermission.MANUAL_VALUE_CHANGES)" to="/admin/versions">
|
||||
{{ t("nav.user.platformVersions") }}
|
||||
<DropdownItem v-if="hasPerms(NamedPermission.MANUAL_VALUE_CHANGES)" to="/admin/settings">
|
||||
{{ t("nav.user.adminSettings") }}
|
||||
</DropdownItem>
|
||||
<DropdownItem v-if="hasPerms(NamedPermission.EDIT_ALL_USER_SETTINGS)" to="/admin/user/">
|
||||
{{ t("nav.user.userList") }}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 6cac2d63bb9d266665b4931cf99bfb6b5742c23e
|
||||
Subproject commit e6e51d36f08276d341a6a8eebc44426848405128
|
@ -91,7 +91,7 @@
|
||||
"stats": "Stats",
|
||||
"health": "Hangar Health",
|
||||
"log": "User Action Log",
|
||||
"platformVersions": "Platform Versions",
|
||||
"adminSettings": "Admin settings",
|
||||
"userList": "User List",
|
||||
"logout": "Sign out",
|
||||
"error": {
|
||||
|
@ -1,8 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { computed, Ref, ref } from "vue";
|
||||
import { cloneDeep, isEqual } from "lodash-es";
|
||||
import { Ref, ref } from "vue";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { PlatformVersion } from "hangar-internal";
|
||||
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
@ -17,6 +16,8 @@ import { useSeo } from "~/composables/useSeo";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import { definePageMeta } from "#imports";
|
||||
import { Platform } from "~/types/enums";
|
||||
import InputText from "~/lib/components/ui/InputText.vue";
|
||||
import { integer } from "~/lib/composables/useValidationHelpers";
|
||||
|
||||
definePageMeta({
|
||||
globalPermsRequired: ["MANUAL_VALUE_CHANGES"],
|
||||
@ -38,7 +39,7 @@ const fullVersions: Ref<Record<Platform, string[]>> = ref({
|
||||
WATERFALL: [],
|
||||
VELOCITY: [],
|
||||
});
|
||||
reset();
|
||||
resetPlatformVersions();
|
||||
|
||||
function versions(versions: PlatformVersion[]): string[] {
|
||||
const fullVersions = [];
|
||||
@ -52,7 +53,7 @@ function versions(versions: PlatformVersion[]): string[] {
|
||||
return fullVersions;
|
||||
}
|
||||
|
||||
async function save() {
|
||||
async function savePlatformVersions() {
|
||||
loading.value = true;
|
||||
const data: { [key: string]: string[] } = {};
|
||||
for (const pl of platforms || []) {
|
||||
@ -68,11 +69,28 @@ async function save() {
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
function resetPlatformVersions() {
|
||||
for (const platform of useBackendData.platforms.values()) {
|
||||
fullVersions.value[platform.enumName] = versions(platform.possibleVersions);
|
||||
}
|
||||
}
|
||||
|
||||
const roles = ref([...useBackendData.orgRoles, ...useBackendData.globalRoles, ...useBackendData.projectRoles]);
|
||||
async function saveRoles() {
|
||||
loading.value = true;
|
||||
const data = [];
|
||||
for (const role of roles.value) {
|
||||
data.push({ roleId: role.roleId, title: role.title, color: role.color, rank: role.rank });
|
||||
}
|
||||
try {
|
||||
await useInternalApi("admin/roles", "post", roles.value);
|
||||
notification.success("Updated roles!");
|
||||
router.go(0);
|
||||
} catch (e: any) {
|
||||
loading.value = false;
|
||||
handleRequestError(e);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -99,10 +117,45 @@ function reset() {
|
||||
<template #footer>
|
||||
<span class="flex justify-end items-center gap-2">
|
||||
Updates may take a while to take effect!
|
||||
<Button @click="reset">{{ i18n.t("general.reset") }}</Button>
|
||||
<Button :disabled="loading" @click="save"> {{ i18n.t("platformVersions.saveChanges") }}</Button>
|
||||
<Button @click="resetPlatformVersions">{{ i18n.t("general.reset") }}</Button>
|
||||
<Button :disabled="loading" @click="savePlatformVersions"> {{ i18n.t("platformVersions.saveChanges") }}</Button>
|
||||
</span>
|
||||
</template>
|
||||
</Card>
|
||||
<div class="mt-5">
|
||||
<Card>
|
||||
<PageTitle>Roles</PageTitle>
|
||||
<Table class="w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Category</th>
|
||||
<th>Color</th>
|
||||
<th>Rank</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="role in roles" :key="role.roleId">
|
||||
<td>
|
||||
<InputText v-model="role.title" />
|
||||
</td>
|
||||
<td>{{ role.roleCategory }}</td>
|
||||
<td>
|
||||
<InputText v-model="role.color" />
|
||||
</td>
|
||||
<td>
|
||||
<InputText v-model="role.rank" :rules="[integer()]" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</Table>
|
||||
|
||||
<template #footer>
|
||||
<span class="flex justify-end items-center gap-2">
|
||||
<Button :disabled="loading" @click="saveRoles"> {{ i18n.t("platformVersions.saveChanges") }}</Button>
|
||||
</span>
|
||||
</template>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
2
frontend/src/types/api/users.d.ts
vendored
2
frontend/src/types/api/users.d.ts
vendored
@ -7,7 +7,7 @@ declare module "hangar-api" {
|
||||
rank?: number | null;
|
||||
value: string;
|
||||
roleId: number;
|
||||
category: RoleCategory;
|
||||
roleCategory: RoleCategory;
|
||||
permissions: string;
|
||||
title: string;
|
||||
color: string;
|
||||
|
Loading…
Reference in New Issue
Block a user