mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-09 03:30:48 +08:00
Block workspace directory picker unless super_admin.
Anonymous and normal users no longer open the OS folder dialog from the empty chat hero; only super_admin can pick/create directories. Host gates directoryPicker.pick/list/createDirectory and the client cancels directoryFlow when canCreateWorkspace is false. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2cf253f6aa
commit
2072c10338
2 changed files with 102 additions and 12 deletions
|
|
@ -835,11 +835,30 @@ window.__ModuleLoader__.load({
|
||||||
const origCall = rpc.call.bind(rpc)
|
const origCall = rpc.call.bind(rpc)
|
||||||
rpc.call = async function udsAuthRpcCall(channel, endpoint, payload, signal) {
|
rpc.call = async function udsAuthRpcCall(channel, endpoint, payload, signal) {
|
||||||
const result = await origCall(channel, endpoint, payload, signal)
|
const result = await origCall(channel, endpoint, payload, signal)
|
||||||
if (getEmpNo()) return result
|
if (!getEmpNo()) {
|
||||||
if (channel !== '/api') return result
|
if (channel === '/api') {
|
||||||
if (endpoint === 'session/list') return { ok: true, value: { items: [] } }
|
if (endpoint === 'session/list') return { ok: true, value: { items: [] } }
|
||||||
if (endpoint === 'session/search') return { ok: true, value: { items: [], hasMore: false } }
|
if (endpoint === 'session/search') return { ok: true, value: { items: [], hasMore: false } }
|
||||||
return result
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
channel === '/api'
|
||||||
|
&& (
|
||||||
|
endpoint === 'directoryPicker/pick'
|
||||||
|
|| endpoint === 'directoryPicker/list'
|
||||||
|
|| endpoint === 'directoryPicker/createDirectory'
|
||||||
|
)
|
||||||
|
&& document.documentElement.getAttribute('data-uds-can-create-ws') !== '1'
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
error: {
|
||||||
|
code: 'gateway/forbidden',
|
||||||
|
message: getEmpNo() ? '只有超级管理员可以创建工作区' : '登录后才能使用工作区',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -882,6 +901,57 @@ window.__ModuleLoader__.load({
|
||||||
}
|
}
|
||||||
}, 'uds-auth: session-list-gate')
|
}, 'uds-auth: session-list-gate')
|
||||||
|
|
||||||
|
|
||||||
|
ctx.effect(() => {
|
||||||
|
let disposers = []
|
||||||
|
const Gate = function UdsAuthDirectoryFlowGate(props) {
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (props && props.open) {
|
||||||
|
try { props.onCancel && props.onCancel() } catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}, [props && props.open])
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const sync = async () => {
|
||||||
|
let canCreate = false
|
||||||
|
try {
|
||||||
|
const me = await fetchJson('/uds-auth/api/me')
|
||||||
|
canCreate = !!(me && me.data && me.data.permissions && me.data.permissions.canCreateWorkspace)
|
||||||
|
} catch { canCreate = false }
|
||||||
|
for (const d of disposers) {
|
||||||
|
try { d() } catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
disposers = []
|
||||||
|
if (canCreate) return
|
||||||
|
for (const slotName of [
|
||||||
|
'sidebar.workspaces.directoryFlow',
|
||||||
|
'conversation.hero.workspace.directoryFlow',
|
||||||
|
]) {
|
||||||
|
try {
|
||||||
|
disposers.push(ctx.slots.register({
|
||||||
|
name: slotName,
|
||||||
|
id: 'uds-auth-dir-gate',
|
||||||
|
order: 9999,
|
||||||
|
}, Gate))
|
||||||
|
} catch { /* slot may be undeclared briefly */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sync()
|
||||||
|
const timer = setInterval(sync, 15000)
|
||||||
|
const onFocus = () => { sync() }
|
||||||
|
const onAuth = () => { sync() }
|
||||||
|
window.addEventListener('focus', onFocus)
|
||||||
|
window.addEventListener('uds-auth-changed', onAuth)
|
||||||
|
return () => {
|
||||||
|
clearInterval(timer)
|
||||||
|
window.removeEventListener('focus', onFocus)
|
||||||
|
window.removeEventListener('uds-auth-changed', onAuth)
|
||||||
|
for (const d of disposers) {
|
||||||
|
try { d() } catch { /* ignore */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 'uds-auth: directory-flow-gate')
|
||||||
|
|
||||||
// sidebar.footer.action; layout effect lays footArea as one row: Settings | UDS login
|
// sidebar.footer.action; layout effect lays footArea as one row: Settings | UDS login
|
||||||
ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({
|
ctx.slots.inject('sidebar.footer.action', () => ctx.slots.register({
|
||||||
name: 'sidebar.footer.action',
|
name: 'sidebar.footer.action',
|
||||||
|
|
|
||||||
|
|
@ -380,19 +380,39 @@ export function installDshAcl(ctx, {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// directory picker: block createDirectory for non-super
|
// directory picker: only super_admin may pick/create dirs (others get auto workspaces)
|
||||||
ctx.inject(['directoryPicker'], (dctx) => {
|
ctx.inject(['directoryPicker'], (dctx) => {
|
||||||
const dp = dctx.directoryPicker
|
const dp = dctx.directoryPicker
|
||||||
if (!dp || dp.__udsAcl) return
|
if (!dp || dp.__udsAcl) return
|
||||||
dp.__udsAcl = true
|
dp.__udsAcl = true
|
||||||
|
|
||||||
|
const assertCanCreateWorkspace = () => {
|
||||||
|
const identity = getUserContext()
|
||||||
|
if (!identity?.empNo) throwForbidden('登录后才能使用工作区')
|
||||||
|
if (!identity?.permissions?.canCreateWorkspace) {
|
||||||
|
throwForbidden('只有超级管理员可以创建工作区')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof dp.pick === 'function') {
|
||||||
|
const origPick = dp.pick.bind(dp)
|
||||||
|
dp.pick = async (...args) => {
|
||||||
|
assertCanCreateWorkspace()
|
||||||
|
return origPick(...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof dp.list === 'function') {
|
||||||
|
const origList = dp.list.bind(dp)
|
||||||
|
dp.list = async (...args) => {
|
||||||
|
assertCanCreateWorkspace()
|
||||||
|
return origList(...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
if (typeof dp.createDirectory === 'function') {
|
if (typeof dp.createDirectory === 'function') {
|
||||||
const orig = dp.createDirectory.bind(dp)
|
const origCreate = dp.createDirectory.bind(dp)
|
||||||
dp.createDirectory = async (...args) => {
|
dp.createDirectory = async (...args) => {
|
||||||
const identity = getUserContext()
|
assertCanCreateWorkspace()
|
||||||
if (!identity?.permissions?.canCreateWorkspace) {
|
return origCreate(...args)
|
||||||
throwForbidden('只有超级管理员可以创建目录/工作区')
|
|
||||||
}
|
|
||||||
return orig(...args)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue