feat: add business line permissions and Wayne namespace mapping

This commit is contained in:
mac
2026-07-17 15:02:18 +08:00
parent e1d755b2df
commit d264924d1e
23 changed files with 1343 additions and 81 deletions
+2
View File
@@ -12,6 +12,7 @@ export interface UserInfo {
display_name: string
email: string
business_line: string
is_admin: boolean
}
export interface LoginResponse {
@@ -113,6 +114,7 @@ export const authApi = {
display_name: data.display_name || data.username,
email: data.email || '',
business_line: data.business_line || '',
is_admin: data.is_admin === true,
},
}
},
+109
View File
@@ -0,0 +1,109 @@
import { getToken } from '@/utils/auth'
export interface BusinessLine {
id: number
name: string
created_at: string
updated_at: string
permission?: 0 | 1
}
export interface WayneNamespace {
id: number
name: string
kubeNamespace: string
}
export const businessLineApi = {
async listMine(): Promise<BusinessLine[]> {
const token = getToken()
const response = await fetch('/auth/api/v1/business-lines', {
headers: {
Accept: 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
})
const data = await response.json().catch(() => ({}))
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`)
}
return Array.isArray(data.items) ? data.items : []
},
async listAll(): Promise<BusinessLine[]> {
const data = await request('/auth/api/v1/business-lines/all')
return Array.isArray(data.items) ? data.items : []
},
async create(name: string): Promise<BusinessLine> {
return request('/auth/api/v1/business-lines', {
method: 'POST',
body: JSON.stringify({ name }),
})
},
async update(id: number, name: string): Promise<BusinessLine> {
return request(`/auth/api/v1/business-lines/${id}`, {
method: 'PUT',
body: JSON.stringify({ name }),
})
},
async remove(id: number): Promise<void> {
await request(`/auth/api/v1/business-lines/${id}`, {
method: 'DELETE',
})
},
async grant(payload: {
business_line_id: number
target_user_id: number
target_business_line_id: number
permission: 0 | 1
}): Promise<void> {
await request('/auth/api/v1/business-lines/authorizations', {
method: 'POST',
body: JSON.stringify(payload),
})
},
async listWayneNamespaces(): Promise<WayneNamespace[]> {
const data = await request('/auth/api/v1/wayne/namespaces')
const items = Array.isArray(data.data) ? data.data : Array.isArray(data.items) ? data.items : []
return items.map((item: any) => ({
id: Number(item.id),
name: item.name || '',
kubeNamespace: item.kubeNamespace || item.kube_namespace || '',
}))
},
async listMappedWayneNamespaces(businessLineId: number): Promise<WayneNamespace[]> {
const data = await request(`/auth/api/v1/business-lines/${businessLineId}/wayne-namespaces`)
return Array.isArray(data.items) ? data.items : []
},
async replaceMappedWayneNamespaces(businessLineId: number, namespaces: WayneNamespace[]): Promise<void> {
await request(`/auth/api/v1/business-lines/${businessLineId}/wayne-namespaces`, {
method: 'PUT',
body: JSON.stringify({ namespaces }),
})
},
}
async function request(path: string, init: RequestInit = {}) {
const token = getToken()
const response = await fetch(path, {
...init,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...init.headers,
},
})
const data = await response.json().catch(() => ({}))
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`)
}
return data
}
+10 -1
View File
@@ -1,6 +1,7 @@
import type { ApiResponse } from '@/types/api'
import { getToken, removeToken } from '@/utils/auth'
import { redirectToSSO } from '@/utils/sso'
import { useBusinessLineStore } from '@/stores/businessLine'
export interface Subsystem {
id: number
@@ -126,7 +127,7 @@ export const subsystemApi = {
const token = getToken()
const openApp = subsystem.name === 'CloudDM' ? 'clouddm' : 'wayne'
const path = subsystem.name === 'CloudDM' ? '/auth/api/v1/clouddm/login' : '/auth/api/v1/wayen/login'
const path = subsystem.name === 'CloudDM' ? '/auth/api/v1/clouddm/login' : wayneLoginPath()
const response = await fetch(path, {
headers: {
Accept: 'application/json',
@@ -164,3 +165,11 @@ export const subsystemApi = {
}
},
}
function wayneLoginPath(): string {
const businessLineID = useBusinessLineStore().current?.id
if (!businessLineID) {
return '/auth/api/v1/wayen/login'
}
return `/auth/api/v1/wayen/login?business_line_id=${encodeURIComponent(String(businessLineID))}`
}
+23
View File
@@ -0,0 +1,23 @@
import { getToken } from '@/utils/auth'
export interface UserOption {
uid: number
username: string
}
export const userApi = {
async list(): Promise<UserOption[]> {
const token = getToken()
const response = await fetch('/auth/api/v1/users', {
headers: {
Accept: 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
})
const data = await response.json().catch(() => ({}))
if (!response.ok) {
throw new Error(data.error || `HTTP ${response.status}`)
}
return Array.isArray(data.items) ? data.items : []
},
}