added permissions logic

This commit is contained in:
ACoolName 2024-05-23 02:08:59 +03:00
parent 39860c84e6
commit b25998da7f
3 changed files with 148 additions and 95 deletions

View File

@ -129,27 +129,6 @@ const definitions = {
],
title: "ImageInfo"
},
InviteUserRequests: {
properties: {
email: {
type: "string",
title: "Email"
},
permissions: {
items: {
"$ref": "#/definitions/Permission"
},
type: "array",
title: "Permissions"
}
},
type: "object",
required: [
"email",
"permissions"
],
title: "InviteUserRequests"
},
PasswordRequestForm: {
properties: {
username: {
@ -345,54 +324,6 @@ const definitions = {
],
title: "SetServerNicknameRequest"
},
SetServerPermissionsRequest: {
properties: {
username: {
type: "string",
title: "Username",
fetch_display_path: "username",
fetch_key_path: "username",
fetch_url: "/users"
},
permissions: {
items: {
"$ref": "#/definitions/Permission"
},
type: "array",
title: "Permissions"
}
},
type: "object",
required: [
"username"
],
title: "SetServerPermissionsRequest"
},
StartServerRequest: {
properties: {
ports: {
items: {
"$ref": "#/definitions/PortMapping"
},
type: "array",
title: "Ports",
default: []
},
command: {
anyOf: [
{
type: "string"
},
{
type: "null"
}
],
title: "Command"
}
},
type: "object",
title: "StartServerRequest"
},
Token: {
properties: {
access_token: {
@ -482,7 +413,29 @@ export const SERVER_ACTIONS: ActionInfo[] = [
{
name: "Start",
args: {
"$ref": "#/definitions/StartServerRequest",
properties: {
ports: {
items: {
"$ref": "#/definitions/PortMapping"
},
type: "array",
title: "Ports",
default: []
},
command: {
anyOf: [
{
type: "string"
},
{
type: "null"
}
],
title: "Command"
}
},
type: "object",
title: "Start Server",
definitions: definitions,
},
requestType: "post",
@ -554,27 +507,66 @@ export const SERVER_ACTIONS: ActionInfo[] = [
response_action: "Browse"
},
{
name: "Set Nickname",
name: "Update Server",
requestType: "patch",
endpoint: "/servers/{server_id}",
permissions: Permission.Admin,
response_action: "Ignore",
args: {
"$ref": "#/definitions/SetServerNicknameRequest",
title: "Update Server",
type: "object",
required: [],
properties: {
DefaultPorts: {
type: "array",
title: "Default Ports",
items:
{
"$ref": "#/definitions/Port-Input"
}
},
DefaultCommand: {
type: "string",
title: "Default Command"
},
Nickname: {
type: "string",
title: "Nickname"
}
},
definitions: definitions,
},
requestType: "post",
endpoint: "/servers/{server_id}/nickname",
permissions: Permission.Admin,
response_action: "Ignore"
},
{
name: "Add Permissions",
args: {
"$ref": "#/definitions/SetServerPermissionsRequest",
definitions: definitions,
},
requestType: "post",
endpoint: "/servers/{server_id}/permissions",
permissions: Permission.Admin,
response_action: "Ignore"
response_action: "Ignore",
args: {
properties: {
username: {
type: "string",
title: "Username",
fetch_display_path: "Username",
fetch_key_path: "Username",
fetch_url: "/users"
},
permissions: {
type: "number",
title: "Permissions",
permissions: true,
}
},
type: "object",
required: [
"username"
],
title: "Set User Permissions",
definitions: definitions,
},
}
]
@ -622,7 +614,22 @@ export const CREATE_SERVER_ACTION: ActionInfo = {
export const INVITE_USER_ACTION: ActionInfo = {
name: "Invite User",
args: {
"$ref": "#/definitions/InviteUserRequests",
properties: {
email: {
type: "string",
title: "Email"
},
permissions: {
type: "number",
title: "Permissions",
permissions: true,
}
},
type: "object",
required: [
"email"
],
title: "Invite User",
definitions: definitions,
},
requestType: "post",

View File

@ -6,8 +6,7 @@ import { Box, Button, ButtonGroup, ButtonOwnProps, Modal, PaletteMode, Paper, Ta
import { Form } from "@rjsf/mui";
import validator from '@rjsf/validator-ajv8';
import { blue, grey } from "@mui/material/colors";
import { OpenAPISchema, User } from "./interfaces";
import { JSONSchema7 } from "json-schema";
import { User } from "./interfaces";
import { IChangeEvent } from "@rjsf/core";
import { RJSFSchema, WidgetProps } from "@rjsf/utils";
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
@ -99,7 +98,7 @@ export function ApiWrapper(p: { children: ReactNode}) {
export interface ActionInfo {
name: string
requestType: 'post' | 'get' | 'delete'
requestType: 'post' | 'get' | 'delete' | 'patch'
endpoint: string
args: {}
permissions?: number
@ -114,14 +113,61 @@ interface Options{
export const actionIdentifierContext: Context<string> = createContext('')
function FetcherField(props: WidgetProps){
function convertNumber(permissions: number): number[]{
var arr: number[] = []
if (permissions&Permission.Start){
arr.push(Permission.Start)
}
if (permissions&Permission.Stop){
arr.push(Permission.Stop)
}
if (permissions&Permission.Browse){
arr.push(Permission.Browse)
}
if (permissions&Permission.RunCommand){
arr.push(Permission.RunCommand)
}
if (permissions&Permission.Create){
arr.push(Permission.Create)
}
if (permissions&Permission.Delete){
arr.push(Permission.Delete)
}
if (permissions&Permission.Admin){
arr.push(Permission.Admin)
}
return arr
}
function CustomField(props: WidgetProps){
const jp = require('jsonpath')
const [options2, setOptions]: [Options[]|null, Dispatch<Options[]>] = useState(null as Options[]|null)
const {schema, registry, options, ...newProps} = props
const {SelectWidget} = registry.widgets
const {SelectWidget, CheckboxesWidget} = registry.widgets
if (!schema.fetch_url){
return <TextField onChange={(event)=>(props.onChange(event.target.value))} value={props.value} label={props.label}/>
if (!schema.permissions){
return <TextField onChange={(event)=>(props.onChange(event.target.value))} value={props.value} label={props.label}/>
}
return <CheckboxesWidget
{...newProps}
onChange={(event)=>{
props.onChange(event.reduce((partialSum: number, a: number) => (partialSum + a), 0))
}
}
schema={{}}
options={{
enumOptions: [
{label: 'Start', value: Permission.Start},
{label: 'Stop', value: Permission.Stop},
{label: 'Browse', value: Permission.Browse},
{label: 'Delete', value: Permission.Delete},
{label: 'RunCommand', value: Permission.RunCommand},
{label: 'Create', value: Permission.Create},
{label: 'Admin', value: Permission.Admin},
]}} registry={registry} value={convertNumber(props.value)} />
}
if (options2 === null){
@ -142,7 +188,6 @@ function FetcherField(props: WidgetProps){
function isUserAllowed(user: User|null, action: ActionInfo): boolean{
console.log({User: user, Action: action})
if (user === null){
return false
}
@ -171,6 +216,7 @@ export function ActionItem(p: { action: ActionInfo, identifierSubstring?: string
const [form, setForm] = useState(false);
const [formData, setFormData]: [RJSFSchema, Dispatch<RJSFSchema>] = useState({})
console.log(formData)
function handleSubmit() {
@ -181,6 +227,10 @@ export function ActionItem(p: { action: ActionInfo, identifierSubstring?: string
promise = api.post(url, formData)
break
}
case 'patch':{
promise = api.patch(url, formData)
break
}
case 'get': {
if (formData){
console.warn('get can get no arguments, dropping')
@ -218,7 +268,7 @@ export function ActionItem(p: { action: ActionInfo, identifierSubstring?: string
open={form}
>
<Box sx={formModalStyle}>
<Form validator={validator} widgets={{TextWidget: FetcherField}} schema={p.action.args} onChange={onFormChange} formData={formData} onSubmit={handleSubmit} />
<Form validator={validator} widgets={{TextWidget: CustomField}} schema={p.action.args} onChange={onFormChange} formData={formData} onSubmit={handleSubmit} />
</Box>
</Modal>
</>)
@ -294,9 +344,6 @@ export function ActionGroup(p: { actions: ActionInfo[], identifierSubstring?: st
<ClickAwayListener onClickAway={handleClose}>
<MenuList id="split-button-menu" autoFocusItem>
{actionItems.map((option, index) => {
if (!option.props){
console.log(actionItems)
}
return <MenuItem
key={option.props.action.name}
selected={index === selectedIndex}

View File

@ -48,7 +48,6 @@ function UserItem(p: { user: User }) {
export function UsersPage({ }) {
const [apiAuthenticated, setApiAuthenticated] = useContext(apiAuthenticatedContext)
const [users, setUsers]: [User[], Dispatch<User[]>] = useState([] as User[])
console.log({apiAuthenticated: apiAuthenticated, users: users})
const action: ActionInfo|undefined = INVITE_USER_ACTION
@ -60,7 +59,7 @@ export function UsersPage({ }) {
setUsers(response.data)
}).catch(
(error) => {
console.log('Failed to get servers: ' + error);
console.log('Failed to get users: ' + error);
if (error.response) {
if (error.response.status === 401) {
setApiAuthenticated(false)