updates to user roles

This commit is contained in:
Henry Dollman
2024-07-17 12:14:07 -04:00
parent 8b09b5092e
commit fe110b1175
8 changed files with 59 additions and 40 deletions

View File

@@ -153,7 +153,7 @@ func main() {
deleteServerConnection(newRecord) deleteServerConnection(newRecord)
} }
// if server is set to pending, try to connect // if server is set to pending (unpause), try to connect
if newStatus == "pending" { if newStatus == "pending" {
go updateServer(newRecord) go updateServer(newRecord)
} }

View File

@@ -15,7 +15,7 @@ func init() {
{ {
"id": "2hz5ncl8tizk5nx", "id": "2hz5ncl8tizk5nx",
"created": "2024-07-07 16:08:20.979Z", "created": "2024-07-07 16:08:20.979Z",
"updated": "2024-07-14 19:51:52.377Z", "updated": "2024-07-17 15:27:00.429Z",
"name": "systems", "name": "systems",
"type": "base", "type": "base",
"system": false, "system": false,
@@ -91,20 +91,36 @@ func init() {
"options": { "options": {
"maxSize": 2000000 "maxSize": 2000000
} }
},
{
"system": false,
"id": "jcarjnjj",
"name": "users",
"type": "relation",
"required": true,
"presentable": false,
"unique": false,
"options": {
"collectionId": "_pb_users_auth_",
"cascadeDelete": false,
"minSelect": null,
"maxSelect": null,
"displayFields": null
}
} }
], ],
"indexes": [], "indexes": [],
"listRule": "", "listRule": "@request.auth.id != \"\" && users.id ?= @request.auth.id",
"viewRule": "@request.auth.id != \"\"", "viewRule": "@request.auth.id != \"\" && users.id ?= @request.auth.id",
"createRule": "@request.auth.id != \"\" && @request.auth.admin = true", "createRule": "@request.auth.id != \"\" && users.id ?= @request.auth.id && @request.auth.role != \"readonly\"",
"updateRule": "", "updateRule": "@request.auth.id != \"\" && users.id ?= @request.auth.id && @request.auth.role != \"readonly\"",
"deleteRule": "@request.auth.id != \"\" && @request.auth.admin = true", "deleteRule": "@request.auth.id != \"\" && users.id ?= @request.auth.id && @request.auth.role != \"readonly\"",
"options": {} "options": {}
}, },
{ {
"id": "ej9oowivz8b2mht", "id": "ej9oowivz8b2mht",
"created": "2024-07-07 16:09:09.179Z", "created": "2024-07-07 16:09:09.179Z",
"updated": "2024-07-14 03:36:23.089Z", "updated": "2024-07-15 22:44:12.297Z",
"name": "system_stats", "name": "system_stats",
"type": "base", "type": "base",
"system": false, "system": false,
@@ -151,7 +167,7 @@ func init() {
{ {
"id": "juohu4jipgc13v7", "id": "juohu4jipgc13v7",
"created": "2024-07-07 16:09:57.976Z", "created": "2024-07-07 16:09:57.976Z",
"updated": "2024-07-14 03:36:23.090Z", "updated": "2024-07-15 22:44:12.297Z",
"name": "container_stats", "name": "container_stats",
"type": "base", "type": "base",
"system": false, "system": false,
@@ -196,11 +212,28 @@ func init() {
{ {
"id": "_pb_users_auth_", "id": "_pb_users_auth_",
"created": "2024-07-14 16:25:18.226Z", "created": "2024-07-14 16:25:18.226Z",
"updated": "2024-07-14 16:25:18.235Z", "updated": "2024-07-17 15:18:01.385Z",
"name": "users", "name": "users",
"type": "auth", "type": "auth",
"system": false, "system": false,
"schema": [ "schema": [
{
"system": false,
"id": "qkbp58ae",
"name": "role",
"type": "select",
"required": true,
"presentable": false,
"unique": false,
"options": {
"maxSelect": 1,
"values": [
"user",
"admin",
"readonly"
]
}
},
{ {
"system": false, "system": false,
"id": "users_avatar", "id": "users_avatar",
@@ -222,16 +255,6 @@ func init() {
"maxSize": 5242880, "maxSize": 5242880,
"protected": false "protected": false
} }
},
{
"system": false,
"id": "ebyl7gfs",
"name": "admin",
"type": "bool",
"required": false,
"presentable": false,
"unique": false,
"options": {}
} }
], ],
"indexes": [], "indexes": [],
@@ -255,7 +278,7 @@ func init() {
{ {
"id": "elngm8x1l60zi2v", "id": "elngm8x1l60zi2v",
"created": "2024-07-15 01:16:04.044Z", "created": "2024-07-15 01:16:04.044Z",
"updated": "2024-07-15 18:48:55.881Z", "updated": "2024-07-15 22:44:12.297Z",
"name": "alerts", "name": "alerts",
"type": "base", "type": "base",
"system": false, "system": false,

View File

@@ -53,6 +53,7 @@ export function AddServerButton() {
const formData = new FormData(e.target as HTMLFormElement) const formData = new FormData(e.target as HTMLFormElement)
const data = Object.fromEntries(formData) as Record<string, any> const data = Object.fromEntries(formData) as Record<string, any>
data.status = 'pending' data.status = 'pending'
data.users = pb.authStore.model!.id
data.info = { data.info = {
cpu: 0, cpu: 0,
m: 0, m: 0,

View File

@@ -55,6 +55,7 @@ export default function DiskChart({
> >
<CartesianGrid vertical={false} /> <CartesianGrid vertical={false} />
<YAxis <YAxis
className="tracking-tighter"
width={75} width={75}
domain={[0, diskSize]} domain={[0, diskSize]}
// ticks={ticks} // ticks={ticks}

View File

@@ -45,7 +45,8 @@ export default function DiskIoChart({
> >
<CartesianGrid vertical={false} /> <CartesianGrid vertical={false} />
<YAxis <YAxis
width={75} className="tracking-tighter"
width={80}
domain={[0, 'auto']} domain={[0, 'auto']}
// ticks={ticks} // ticks={ticks}
tickCount={9} tickCount={9}

View File

@@ -60,7 +60,7 @@ import { useMemo, useState } from 'react'
import { $systems, pb, navigate } from '@/lib/stores' import { $systems, pb, navigate } from '@/lib/stores'
import { useStore } from '@nanostores/react' import { useStore } from '@nanostores/react'
import { AddServerButton } from '../add-server' import { AddServerButton } from '../add-server'
import { cn, copyToClipboard, isAdmin } from '@/lib/utils' import { cn, copyToClipboard, isReadOnlyUser } from '@/lib/utils'
import AlertsButton from '../table-alerts' import AlertsButton from '../table-alerts'
function CellFormatter(info: CellContext<SystemRecord, unknown>) { function CellFormatter(info: CellContext<SystemRecord, unknown>) {
@@ -167,15 +167,8 @@ export default function SystemsTable() {
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
{/* <DropdownMenuLabel>Actions</DropdownMenuLabel> */}
{/* <DropdownMenuItem
onSelect={() => {
navigate(`/server/${name}`)
}}
>
View details
</DropdownMenuItem> */}
<DropdownMenuItem <DropdownMenuItem
className={cn(isReadOnlyUser() && 'hidden')}
onClick={() => { onClick={() => {
pb.collection('systems').update(id, { pb.collection('systems').update(id, {
status: status === 'paused' ? 'pending' : 'paused', status: status === 'paused' ? 'pending' : 'paused',
@@ -198,9 +191,9 @@ export default function SystemsTable() {
<CopyIcon className="mr-2.5 h-4 w-4" /> <CopyIcon className="mr-2.5 h-4 w-4" />
Copy host Copy host
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuSeparator /> <DropdownMenuSeparator className={cn(isReadOnlyUser() && 'hidden')} />
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<DropdownMenuItem> <DropdownMenuItem className={cn(isReadOnlyUser() && 'hidden')}>
<Trash2Icon className="mr-2.5 h-4 w-4" /> <Trash2Icon className="mr-2.5 h-4 w-4" />
Delete Delete
</DropdownMenuItem> </DropdownMenuItem>
@@ -264,11 +257,9 @@ export default function SystemsTable() {
onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)} onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)}
className="max-w-sm" className="max-w-sm"
/> />
{isAdmin() && ( <div className={cn('ml-auto flex gap-2', isReadOnlyUser() && 'hidden')}>
<div className="ml-auto flex gap-2"> <AddServerButton />
<AddServerButton /> </div>
</div>
)}
</div> </div>
<div className="rounded-md border overflow-hidden"> <div className="rounded-md border overflow-hidden">
<Table> <Table>

View File

@@ -95,7 +95,7 @@ export function UserAuthForm({
email, email,
password, password,
passwordConfirm: password, passwordConfirm: password,
admin: true, role: 'admin',
verified: true, verified: true,
}) })
await pb.collection('users').authWithPassword(email, password) await pb.collection('users').authWithPassword(email, password)

View File

@@ -75,7 +75,9 @@ export const formatDay = (timestamp: string) => {
export const updateFavicon = (newIconUrl: string) => export const updateFavicon = (newIconUrl: string) =>
((document.querySelector("link[rel='icon']") as HTMLLinkElement).href = newIconUrl) ((document.querySelector("link[rel='icon']") as HTMLLinkElement).href = newIconUrl)
export const isAdmin = () => pb.authStore.model?.admin export const isAdmin = () => pb.authStore.model?.role === 'admin'
export const isReadOnlyUser = () => pb.authStore.model?.role === 'readonly'
// export const isDefaultUser = () => pb.authStore.model?.role === 'user'
/** Update systems / alerts list when records change */ /** Update systems / alerts list when records change */
export function updateRecordList<T extends RecordModel>( export function updateRecordList<T extends RecordModel>(