fix(clusters): scope cluster pickers to the owning org
Cluster pickers listed every visible cluster, which includes clusters shared with all authenticated users (e.g. the default org's "shared with everyone" clusters). A member of a custom org could then pick another org's cluster for a model deployment or a new worker. Request only the current org's own clusters (mine=true) for: - the model deploy picker (models page), - the deploy-from-model-file picker (model files page), and - the add-worker picker. These resources are owner-scoped on the backend, so the model list and the worker table (including its cluster-name column) only reference own-org clusters. The add-model-file worker cascader is already own-org via the owner-scoped worker list. Platform admin in the "All" view bypasses mine and is scoped instead by the org picker.
This commit is contained in:
@@ -22,7 +22,12 @@ export const useQueryClusterList = (options?: { useStateData?: boolean }) => {
|
|||||||
loading,
|
loading,
|
||||||
cancel
|
cancel
|
||||||
} = useRequest(
|
} = useRequest(
|
||||||
async (params: { page: number; perPage?: number }) => {
|
async (params: {
|
||||||
|
page: number;
|
||||||
|
perPage?: number;
|
||||||
|
mine?: boolean;
|
||||||
|
gpu_instance_enabled?: boolean;
|
||||||
|
}) => {
|
||||||
axiosTokenRef.current?.cancel();
|
axiosTokenRef.current?.cancel();
|
||||||
axiosTokenRef.current = createAxiosToken();
|
axiosTokenRef.current = createAxiosToken();
|
||||||
const res = await queryClusterList(params, {
|
const res = await queryClusterList(params, {
|
||||||
|
|||||||
@@ -199,7 +199,13 @@ export const useGenerateWorkerOptions = () => {
|
|||||||
page: -1
|
page: -1
|
||||||
}),
|
}),
|
||||||
queryClusterList({
|
queryClusterList({
|
||||||
page: -1
|
page: -1,
|
||||||
|
// Own-org clusters only. Feeds the deploy-from-model-file cluster
|
||||||
|
// picker, which must not offer another org's cluster (e.g. the
|
||||||
|
// Default org's "shared with everyone" clusters). The worker
|
||||||
|
// cascader on this page is already own-org via the owner-scoped
|
||||||
|
// worker list.
|
||||||
|
mine: true
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
const workerList = workerRes.items || ([] as WorkerListItem[]);
|
const workerList = workerRes.items || ([] as WorkerListItem[]);
|
||||||
@@ -272,7 +278,13 @@ export default function useFormInitialValues() {
|
|||||||
// Exclude clusters that opt in to GPU-instance handling
|
// Exclude clusters that opt in to GPU-instance handling
|
||||||
// (k8s_options.gpu_instance_options set) — those are for the
|
// (k8s_options.gpu_instance_options set) — those are for the
|
||||||
// GPU-service flow, not model deployment.
|
// GPU-service flow, not model deployment.
|
||||||
gpu_instance_enabled: false
|
gpu_instance_enabled: false,
|
||||||
|
// Only clusters owned by the current org. Drops cross-org grants
|
||||||
|
// (e.g. the Default org's "shared with everyone" clusters) so a
|
||||||
|
// tenant can't deploy onto another org's infrastructure. Platform
|
||||||
|
// admin in the "All" view bypasses this and is scoped instead by
|
||||||
|
// the org picker (see basic.tsx).
|
||||||
|
mine: true
|
||||||
});
|
});
|
||||||
const list = response.items.map((item) => ({
|
const list = response.items.map((item) => ({
|
||||||
label: item.name,
|
label: item.name,
|
||||||
|
|||||||
@@ -103,8 +103,14 @@ const Workers: React.FC<WorkersProps> = ({ clusterId, source }) => {
|
|||||||
|
|
||||||
const getClusterList = async () => {
|
const getClusterList = async () => {
|
||||||
try {
|
try {
|
||||||
|
// Own-org clusters only (mine=true). A worker can only join a cluster
|
||||||
|
// its org owns, so another org's cluster (e.g. the Default org's
|
||||||
|
// "shared with everyone" clusters) must not be offered in the picker.
|
||||||
|
// The worker list is owner-scoped too, so this list also covers every
|
||||||
|
// cluster the table's name column can reference.
|
||||||
const params = {
|
const params = {
|
||||||
page: -1
|
page: -1,
|
||||||
|
mine: true
|
||||||
};
|
};
|
||||||
const items = await fetchClusterList(params);
|
const items = await fetchClusterList(params);
|
||||||
const clusterMap = items?.reduce(
|
const clusterMap = items?.reduce(
|
||||||
|
|||||||
Reference in New Issue
Block a user