feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { useDestorySpace } from './space/use-destory-space';
export { useSpaceAuth } from './space/use-space-auth';
export { ESpacePermisson, SpaceRoleType } from './space/constants';
export { useSpaceRole } from './space/use-space-role';
export { useSpaceAuthStore } from './space/store';
export { useProjectAuth } from './project/use-project-auth';
export { useDestoryProject } from './project/use-destory-project';
export { EProjectPermission, ProjectRoleType } from './project/constants';
export { useProjectRole } from './project/use-project-role';
export { useProjectAuthStore } from './project/store';

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SpaceRoleType, SpaceType } from '@coze-arch/idl/developer_api';
import { ProjectRoleType, EProjectPermission } from './constants';
const projectRolePermissionMapOfTeamSpace = {
[ProjectRoleType.Owner]: [
EProjectPermission.View,
EProjectPermission.EDIT_INFO,
EProjectPermission.DELETE,
EProjectPermission.PUBLISH,
EProjectPermission.CREATE_RESOURCE,
EProjectPermission.COPY_RESOURCE,
EProjectPermission.COPY,
EProjectPermission.TEST_RUN_PLUGIN,
EProjectPermission.TEST_RUN_WORKFLOW,
EProjectPermission.ADD_COLLABORATOR,
EProjectPermission.DELETE_COLLABORATOR,
EProjectPermission.ROLLBACK,
],
[ProjectRoleType.Editor]: [
EProjectPermission.View,
EProjectPermission.EDIT_INFO,
EProjectPermission.CREATE_RESOURCE,
EProjectPermission.COPY_RESOURCE,
EProjectPermission.COPY,
EProjectPermission.TEST_RUN_PLUGIN,
EProjectPermission.TEST_RUN_WORKFLOW,
EProjectPermission.ADD_COLLABORATOR,
],
};
const spaceRolePermissionMapOfTeamSpace = {
[SpaceRoleType.Member]: [
EProjectPermission.View,
EProjectPermission.COPY,
EProjectPermission.TEST_RUN_WORKFLOW,
],
[SpaceRoleType.Owner]: [
EProjectPermission.View,
EProjectPermission.COPY,
EProjectPermission.TEST_RUN_WORKFLOW,
],
[SpaceRoleType.Admin]: [
EProjectPermission.View,
EProjectPermission.COPY,
EProjectPermission.TEST_RUN_WORKFLOW,
],
[SpaceRoleType.Default]: [] as EProjectPermission[],
};
const personalSpacePermission = [
EProjectPermission.View,
EProjectPermission.EDIT_INFO,
EProjectPermission.PUBLISH,
EProjectPermission.DELETE,
EProjectPermission.CREATE_RESOURCE,
EProjectPermission.COPY_RESOURCE,
EProjectPermission.COPY,
EProjectPermission.TEST_RUN_PLUGIN,
EProjectPermission.TEST_RUN_WORKFLOW,
EProjectPermission.ROLLBACK,
];
export function calcPermission(
key: EProjectPermission,
{
projectRoles,
spaceRoles,
spaceType,
}: {
projectRoles: ProjectRoleType[];
spaceRoles: SpaceRoleType[];
spaceType: SpaceType;
},
) {
if (spaceType === SpaceType.Personal) {
return personalSpacePermission.includes(key);
} else {
for (const projectRole of projectRoles) {
if (projectRolePermissionMapOfTeamSpace[projectRole]?.includes(key)) {
return true;
}
}
for (const spaceRole of spaceRoles) {
if (spaceRolePermissionMapOfTeamSpace[spaceRole]?.includes(key)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// TODO: 替换成Project接口导出的idl
export enum ProjectRoleType {
Owner = 'owner',
Editor = 'editor',
}
export enum EProjectPermission {
/**
* 访问/查看project
*/
View,
/**
* 编辑project基础信息
*/
EDIT_INFO,
/**
* 删除project
*/
DELETE,
/**
* 发布project
*/
PUBLISH,
/**
* 创建project内资源
*/
CREATE_RESOURCE,
/**
* 在project内复制资源
*/
COPY_RESOURCE,
/**
* 复制project/创建副本
*/
COPY,
/**
* 试运行plugin
*/
TEST_RUN_PLUGIN,
/**
* 试运行workflow
*/
TEST_RUN_WORKFLOW,
/**
* 添加project协作者
*/
ADD_COLLABORATOR,
/**
* 删除project协作者
*/
DELETE_COLLABORATOR,
/**
* 回滚 APP 版本
*/
ROLLBACK,
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { devtools } from 'zustand/middleware';
import { create } from 'zustand';
import { type ProjectRoleType } from './constants';
interface ProjectAuthStoreState {
// 每一个Project的角色数据
roles: {
[projectId: string]: ProjectRoleType[];
};
// 每一个Project的角色数据的初始化状态是否完成初始化。
isReady: {
[projectId: string]: boolean;
};
}
interface SpaceAuthStoreAction {
// 设置projectId对应的Project的角色
setRoles: (projectId: string, role: ProjectRoleType[]) => void;
// 设置projectId对应的Project的数据是否ready
setIsReady: (projectId: string, isReady: boolean) => void;
// 回收Project数据
destory: (projectId) => void;
}
/**
* ProjectAuthStore设计成支持多Project切换维护多个Project的数据防止因为Project切换时序导致的bug。
*/
export const useProjectAuthStore = create<
ProjectAuthStoreState & SpaceAuthStoreAction
>()(
devtools(
set => ({
roles: {},
isReady: {},
setRoles: (projectId, roles) =>
set(state => ({
roles: {
...state.roles,
[projectId]: roles,
},
})),
setIsReady: (projectId, isReady) =>
set(state => ({ isReady: { ...state.isReady, [projectId]: isReady } })),
destory: projectId =>
set(state => ({
roles: { ...state.roles, [projectId]: [] },
isReady: { ...state.isReady, [projectId]: false },
})),
}),
{
enabled: IS_DEV_MODE,
name: 'botStudio.projectAuthStore',
},
),
);

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect } from 'react';
import { useProjectAuthStore } from './store';
export function useDestoryProject(projectId: string) {
const destorySpace = useProjectAuthStore(store => store.destory);
return useEffect(
() => () => {
// 空间组件销毁时清空对应space数据
destorySpace(projectId);
},
[],
);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useSpace } from '@coze-arch/foundation-sdk';
import { useSpaceRole } from '../space/use-space-role';
import { useProjectRole } from './use-project-role';
import { type EProjectPermission } from './constants';
import { calcPermission } from './calc-permission';
export function useProjectAuth(
key: EProjectPermission,
projectId: string,
spaceId: string,
) {
// 获取space类型信息
const space = useSpace(spaceId);
if (!space?.space_type) {
throw new Error(
'useSpaceAuth must be used after space list has been pulled.',
);
}
// 获取space role信息
const spaceRoles = useSpaceRole(spaceId);
// 获取project role信息
const projectRoles = useProjectRole(projectId);
// 计算权限点
return calcPermission(key, {
projectRoles,
spaceRoles,
spaceType: space.space_type,
});
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useShallow } from 'zustand/react/shallow';
import { useProjectAuthStore } from './store';
import { type ProjectRoleType } from './constants';
export function useProjectRole(projectId: string): ProjectRoleType[] {
const { isReady: isProjectReady, role: projectRole = [] } =
useProjectAuthStore(
useShallow(store => ({
isReady: store.isReady[projectId],
role: store.roles[projectId],
})),
);
if (!isProjectReady) {
throw new Error(
'useProjectAuth must be used after useInitProjectRole has been completed.',
);
}
return projectRole;
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SpaceRoleType } from '@coze-arch/idl/developer_api';
import { ESpacePermisson } from './constants';
const permissionMap = {
[SpaceRoleType.Owner]: [
ESpacePermisson.UpdateSpace,
ESpacePermisson.DeleteSpace,
ESpacePermisson.AddBotSpaceMember,
ESpacePermisson.RemoveSpaceMember,
ESpacePermisson.TransferSpace,
ESpacePermisson.UpdateSpaceMember,
ESpacePermisson.API,
],
[SpaceRoleType.Admin]: [
ESpacePermisson.AddBotSpaceMember,
ESpacePermisson.RemoveSpaceMember,
ESpacePermisson.ExitSpace,
ESpacePermisson.UpdateSpaceMember,
],
[SpaceRoleType.Member]: [ESpacePermisson.ExitSpace],
// [SpaceRoleType.Default]: [],
};
export const calcPermission = (
key: ESpacePermisson,
roles: SpaceRoleType[],
) => {
for (const role of roles) {
if (permissionMap[role]?.includes(key)) {
return true;
}
}
return false;
};

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 空间相关的权限点枚举
*/
export enum ESpacePermisson {
/**
* 更新空间
*/
UpdateSpace,
/**
* 删除空间
*/
DeleteSpace,
/**
* 添加成员
*/
AddBotSpaceMember,
/**
* 移除空间成员
*/
RemoveSpaceMember,
/**
* 退出空间
*/
ExitSpace,
/**
* 转移owner权限
*/
TransferSpace,
/**
* 更新成员
*/
UpdateSpaceMember,
/**
* 管理API-KEY
*/
API,
}
/**
* 空间角色枚举
*/
export { SpaceRoleType } from '@coze-arch/idl/developer_api';

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { devtools } from 'zustand/middleware';
import { create } from 'zustand';
import { type SpaceRoleType } from '@coze-arch/idl/developer_api';
interface SpaceAuthStoreState {
// 每一个空间的角色数据
roles: {
[spaceId: string]: SpaceRoleType[];
};
// 每一个空间的角色数据的初始化状态,是否完成初始化。
isReady: {
[spaceId: string]: boolean;
};
}
interface SpaceAuthStoreAction {
// 设置spaceId对应的空间的角色
setRoles: (spaceId: string, roles: SpaceRoleType[]) => void;
// 设置spaceId对应的空间的数据是否ready
setIsReady: (spaceId: string, isReady: boolean) => void;
// 回收空间数据
destory: (spaceId) => void;
}
/**
* SpaceAuthStore设计成支持多空间切换维护多个空间的数据位置因为空间切换时序导致的bug。
*/
export const useSpaceAuthStore = create<
SpaceAuthStoreState & SpaceAuthStoreAction
>()(
devtools(
set => ({
roles: {},
isReady: {},
setRoles: (spaceId, roles) =>
set(state => ({
roles: {
...state.roles,
[spaceId]: roles,
},
})),
setIsReady: (spaceId, isReady) =>
set(state => ({ isReady: { ...state.isReady, [spaceId]: isReady } })),
destory: spaceId =>
set(state => ({
roles: { ...state.roles, [spaceId]: [] },
isReady: { ...state.isReady, [spaceId]: undefined },
})),
}),
{
enabled: IS_DEV_MODE,
name: 'botStudio.spaceAuthStore',
},
),
);

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useEffect } from 'react';
import { useSpaceAuthStore } from './store';
export function useDestorySpace(spaceId: string) {
const destorySpace = useSpaceAuthStore(store => store.destory);
return useEffect(
() => () => {
// 空间组件销毁时清空对应space数据
destorySpace(spaceId);
},
[],
);
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useSpaceRole } from './use-space-role';
import { type ESpacePermisson } from './constants';
import { calcPermission } from './calc-permission';
export function useSpaceAuth(key: ESpacePermisson, spaceId: string) {
// 获取space role信息
const role = useSpaceRole(spaceId);
// 计算权限点
return calcPermission(key, role);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useShallow } from 'zustand/react/shallow';
import { useSpace } from '@coze-arch/foundation-sdk';
import { useSpaceAuthStore } from './store';
export function useSpaceRole(spaceId: string) {
// 获取space信息已有hook。
const space = useSpace(spaceId);
if (!space) {
throw new Error(
'useSpaceAuth must be used after space list has been pulled.',
);
}
const { isReady, role } = useSpaceAuthStore(
useShallow(store => ({
isReady: store.isReady[spaceId],
role: store.roles[spaceId],
})),
);
if (!isReady) {
throw new Error(
'useSpaceAuth must be used after useInitSpaceRole has been completed.',
);
}
if (!role) {
throw new Error(`Can not get space role of space: ${spaceId}`);
}
return role;
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2025 coze-dev Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
declare const IS_DEV_MODE: boolean;
/// <reference types='@coze-arch/bot-typings' />