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,
|
||||
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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user