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:
gitlawr
2026-07-08 20:12:00 +08:00
committed by jialin
parent 70229a9757
commit cd4b1b8629
3 changed files with 27 additions and 4 deletions
@@ -22,7 +22,12 @@ export const useQueryClusterList = (options?: { useStateData?: boolean }) => {
loading,
cancel
} = useRequest(
async (params: { page: number; perPage?: number }) => {
async (params: {
page: number;
perPage?: number;
mine?: boolean;
gpu_instance_enabled?: boolean;
}) => {
axiosTokenRef.current?.cancel();
axiosTokenRef.current = createAxiosToken();
const res = await queryClusterList(params, {
@@ -199,7 +199,13 @@ export const useGenerateWorkerOptions = () => {
page: -1
}),
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[]);
@@ -272,7 +278,13 @@ export default function useFormInitialValues() {
// Exclude clusters that opt in to GPU-instance handling
// (k8s_options.gpu_instance_options set) — those are for the
// 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) => ({
label: item.name,
+7 -1
View File
@@ -103,8 +103,14 @@ const Workers: React.FC<WorkersProps> = ({ clusterId, source }) => {
const getClusterList = async () => {
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 = {
page: -1
page: -1,
mine: true
};
const items = await fetchClusterList(params);
const clusterMap = items?.reduce(