diff --git a/bin/core/src/api/read/mod.rs b/bin/core/src/api/read/mod.rs index bb7af9536..1d35b309a 100644 --- a/bin/core/src/api/read/mod.rs +++ b/bin/core/src/api/read/mod.rs @@ -45,7 +45,7 @@ enum ReadRequest { ListApiKeys(ListApiKeys), ListPermissions(ListPermissions), GetPermissionLevel(GetPermissionLevel), - ListUserPermissions(ListUserPermissions), + ListUserTargetPermissions(ListUserTargetPermissions), // ==== USER GROUP ==== GetUserGroup(GetUserGroup), diff --git a/bin/core/src/api/read/permission.rs b/bin/core/src/api/read/permission.rs index 1aa4b2459..9cee294eb 100644 --- a/bin/core/src/api/read/permission.rs +++ b/bin/core/src/api/read/permission.rs @@ -3,8 +3,8 @@ use axum::async_trait; use monitor_client::{ api::read::{ GetPermissionLevel, GetPermissionLevelResponse, ListPermissions, - ListPermissionsResponse, ListUserPermissions, - ListUserPermissionsResponse, + ListPermissionsResponse, ListUserTargetPermissions, + ListUserTargetPermissionsResponse, }, entities::{permission::PermissionLevel, user::User}, }; @@ -52,20 +52,21 @@ impl Resolve for State { } #[async_trait] -impl Resolve for State { +impl Resolve for State { async fn resolve( &self, - ListUserPermissions { user_id }: ListUserPermissions, + ListUserTargetPermissions { user_target }: ListUserTargetPermissions, user: User, - ) -> anyhow::Result { + ) -> anyhow::Result { if !user.admin { return Err(anyhow!("this method is admin only")); } + let (variant, id) = user_target.extract_variant_id(); find_collect( &db_client().await.permissions, doc! { - "user_target.type": "User", - "user_target.id": user_id + "user_target.type": variant.as_ref(), + "user_target.id": id }, None, ) diff --git a/client/core/rs/src/api/execute/build.rs b/client/core/rs/src/api/execute/build.rs index 96a5ae54f..ae38a5dee 100644 --- a/client/core/rs/src/api/execute/build.rs +++ b/client/core/rs/src/api/execute/build.rs @@ -23,6 +23,9 @@ pub struct RunBuild { // +/// Cancels the target build. +/// Only does anything if the build is `building` when called. +/// Response: [Update] #[typeshare] #[derive( Serialize, Deserialize, Debug, Clone, Request, EmptyTraits, diff --git a/client/core/rs/src/api/read/permission.rs b/client/core/rs/src/api/read/permission.rs index c03136afb..1517dae7d 100644 --- a/client/core/rs/src/api/read/permission.rs +++ b/client/core/rs/src/api/read/permission.rs @@ -4,13 +4,15 @@ use serde::{Deserialize, Serialize}; use typeshare::typeshare; use crate::entities::{ - permission::{Permission, PermissionLevel}, + permission::{Permission, PermissionLevel, UserTarget}, update::ResourceTarget, }; use super::MonitorReadRequest; -/// List permissions for the calling user. Response: [ListPermissionsResponse] +/// List permissions for the calling user. +/// Does not include any permissions on UserGroups they may be a part of. +/// Response: [ListPermissionsResponse] #[typeshare] #[derive( Serialize, Deserialize, Debug, Clone, Request, EmptyTraits, @@ -24,7 +26,9 @@ pub type ListPermissionsResponse = Vec; // -/// Gets the calling user's permission level on a specific resource. Response: [PermissionLevel] +/// Gets the calling user's permission level on a specific resource. +/// Factors in any UserGroup's permissions they may be a part of. +/// Response: [PermissionLevel] #[typeshare] #[derive( Serialize, Deserialize, Debug, Clone, Request, EmptyTraits, @@ -40,16 +44,17 @@ pub type GetPermissionLevelResponse = PermissionLevel; // -/// List permissions for a specific user. Admin only. Response: [ListUserPermissionsResponse] +/// List permissions for a specific user. **Admin only**. +/// Response: [ListUserTargetPermissionsResponse] #[typeshare] #[derive( Serialize, Deserialize, Debug, Clone, Request, EmptyTraits, )] #[empty_traits(MonitorReadRequest)] -#[response(ListUserPermissionsResponse)] -pub struct ListUserPermissions { - pub user_id: String, +#[response(ListUserTargetPermissionsResponse)] +pub struct ListUserTargetPermissions { + pub user_target: UserTarget, } #[typeshare] -pub type ListUserPermissionsResponse = Vec; +pub type ListUserTargetPermissionsResponse = Vec; diff --git a/client/core/ts/src/responses.ts b/client/core/ts/src/responses.ts index b1e2b0481..e2e65cfd4 100644 --- a/client/core/ts/src/responses.ts +++ b/client/core/ts/src/responses.ts @@ -18,7 +18,7 @@ export type ReadResponses = { ListApiKeys: Types.ListApiKeysResponse; ListPermissions: Types.ListPermissionsResponse; GetPermissionLevel: Types.GetPermissionLevelResponse; - ListUserPermissions: Types.ListUserPermissionsResponse; + ListUserTargetPermissions: Types.ListUserTargetPermissionsResponse; // ==== USER GROUP ==== GetUserGroup: Types.GetUserGroupResponse; diff --git a/client/core/ts/src/types.ts b/client/core/ts/src/types.ts index 3a253a8e9..04244b515 100644 --- a/client/core/ts/src/types.ts +++ b/client/core/ts/src/types.ts @@ -553,7 +553,7 @@ export type ListPermissionsResponse = Permission[]; export type GetPermissionLevelResponse = PermissionLevel; -export type ListUserPermissionsResponse = Permission[]; +export type ListUserTargetPermissionsResponse = Permission[]; export enum ProcedureType { /** Run the executions one after the other, in order of increasing index. */ @@ -1187,6 +1187,11 @@ export interface RunBuild { build: string; } +/** + * Cancels the target build. + * Only does anything if the build is `building` when called. + * Response: [Update] + */ export interface CancelBuild { /** Can be id or name */ build: string; @@ -1461,18 +1466,29 @@ export interface GetCoreInfoResponse { github_webhook_base_url: string; } -/** List permissions for the calling user. Response: [ListPermissionsResponse] */ +/** + * List permissions for the calling user. + * Does not include any permissions on UserGroups they may be a part of. + * Response: [ListPermissionsResponse] + */ export interface ListPermissions { } -/** Gets the calling user's permission level on a specific resource. Response: [PermissionLevel] */ +/** + * Gets the calling user's permission level on a specific resource. + * Factors in any UserGroup's permissions they may be a part of. + * Response: [PermissionLevel] + */ export interface GetPermissionLevel { target: ResourceTarget; } -/** List permissions for a specific user. Admin only. Response: [ListUserPermissionsResponse] */ -export interface ListUserPermissions { - user_id: string; +/** + * List permissions for a specific user. **Admin only**. + * Response: [ListUserTargetPermissionsResponse] + */ +export interface ListUserTargetPermissions { + user_target: UserTarget; } export interface GetProcedure { @@ -2124,7 +2140,7 @@ export type ReadRequest = | { type: "ListApiKeys", params: ListApiKeys } | { type: "ListPermissions", params: ListPermissions } | { type: "GetPermissionLevel", params: GetPermissionLevel } - | { type: "ListUserPermissions", params: ListUserPermissions } + | { type: "ListUserTargetPermissions", params: ListUserTargetPermissions } | { type: "GetUserGroup", params: GetUserGroup } | { type: "ListUserGroups", params: ListUserGroups } | { type: "FindResources", params: FindResources } diff --git a/frontend/package.json b/frontend/package.json index f341c8857..35f4a0696 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -55,7 +55,7 @@ "postcss": "8.4.38", "tailwindcss": "3.4.3", "typescript": "5.4.5", - "vite": "5.2.9", + "vite": "5.2.10", "vite-tsconfig-paths": "4.3.2" } } diff --git a/frontend/src/pages/users.tsx b/frontend/src/pages/users.tsx index 5528aa04d..51dc2a072 100644 --- a/frontend/src/pages/users.tsx +++ b/frontend/src/pages/users.tsx @@ -133,14 +133,18 @@ export const UserPage = () => { ) } > - {!user.admin && } + {!user.admin && ( + + )} ) ); }; -const useUserPermissions = (user_id: string) => { - const permissions = useRead("ListUserPermissions", { user_id }).data; +const useUserTargetPermissions = (user_target: Types.UserTarget) => { + const permissions = useRead("ListUserTargetPermissions", { + user_target, + }).data; const servers = useRead("ListServers", {}).data; const deployments = useRead("ListDeployments", {}).data; const builds = useRead("ListBuilds", {}).data; @@ -149,18 +153,18 @@ const useUserPermissions = (user_id: string) => { const builders = useRead("ListBuilders", {}).data; const alerters = useRead("ListAlerters", {}).data; const perms: (Types.Permission & { name: string })[] = []; - addPerms(user_id, permissions, "Server", servers, perms); - addPerms(user_id, permissions, "Deployment", deployments, perms); - addPerms(user_id, permissions, "Build", builds, perms); - addPerms(user_id, permissions, "Repo", repos, perms); - addPerms(user_id, permissions, "Procedure", procedures, perms); - addPerms(user_id, permissions, "Builder", builders, perms); - addPerms(user_id, permissions, "Alerter", alerters, perms); + addPerms(user_target, permissions, "Server", servers, perms); + addPerms(user_target, permissions, "Deployment", deployments, perms); + addPerms(user_target, permissions, "Build", builds, perms); + addPerms(user_target, permissions, "Repo", repos, perms); + addPerms(user_target, permissions, "Procedure", procedures, perms); + addPerms(user_target, permissions, "Builder", builders, perms); + addPerms(user_target, permissions, "Alerter", alerters, perms); return perms; }; function addPerms( - user_id: string, + user_target: Types.UserTarget, permissions: Types.Permission[] | undefined, resource_type: UsableResource, resources: Types.ResourceListItem[] | undefined, @@ -176,7 +180,7 @@ function addPerms( perms.push({ ...perm, name: resource.name }); } else { perms.push({ - user_target: { type: "User", id: user_id }, + user_target, name: resource.name, level: Types.PermissionLevel.None, resource_target: { type: resource_type, id: resource.id }, @@ -185,7 +189,11 @@ function addPerms( }); } -const PermissionsTable = () => { +const PermissionsTable = ({ + user_target, +}: { + user_target: Types.UserTarget; +}) => { const { toast } = useToast(); const [showNone, setShowNone] = useState(false); const [resourceType, setResourceType] = useState( @@ -194,12 +202,11 @@ const PermissionsTable = () => { const [search, setSearch] = useState(""); const searchSplit = search.toLowerCase().split(" "); const inv = useInvalidate(); - const user_id = useParams().id as string; - const permissions = useUserPermissions(user_id); + const permissions = useUserTargetPermissions(user_target); const { mutate } = useWrite("UpdatePermissionOnTarget", { onSuccess: () => { - toast({ title: "Updated user permission" }); - inv(["ListUserPermissions"]); + toast({ title: "Updated permission" }); + inv(["ListUserTargetPermissions"]); }, }); return ( @@ -330,7 +337,7 @@ const PermissionsTable = () => { onValueChange={(value) => mutate({ ...permission, - user_target: { type: "User", id: user_id }, + user_target, permission: value as Types.PermissionLevel, }) } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1a400211d..164fc9eab 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2805,10 +2805,10 @@ vite-tsconfig-paths@4.3.2: globrex "^0.1.2" tsconfck "^3.0.3" -vite@5.2.9: - version "5.2.9" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.9.tgz#cd9a356c6ff5f7456c09c5ce74068ffa8df743d9" - integrity sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw== +vite@5.2.10: + version "5.2.10" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.10.tgz#2ac927c91e99d51b376a5c73c0e4b059705f5bd7" + integrity sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw== dependencies: esbuild "^0.20.1" postcss "^8.4.38"