Skip to content

Commit 8fdbf5a

Browse files
committed
[Fix]: #1904 add permissions data sources
1 parent b990841 commit 8fdbf5a

File tree

4 files changed

+101
-29
lines changed

4 files changed

+101
-29
lines changed

client/packages/lowcoder/src/components/PermissionDialog/DatasourcePermissionDialog.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { DatasourceRole } from "../../api/datasourcePermissionApi";
1313
import { getDataSourcePermissionInfo } from "../../redux/selectors/datasourceSelectors";
1414
import { StyledLoading } from "./commonComponents";
1515
import { PermissionRole } from "./Permission";
16+
import { getUser } from "../../redux/selectors/usersSelectors";
1617

1718
export const DatasourcePermissionDialog = (props: {
1819
datasourceId: string;
@@ -22,6 +23,7 @@ export const DatasourcePermissionDialog = (props: {
2223
const { datasourceId } = props;
2324
const dispatch = useDispatch();
2425
const permissionInfo = useSelector(getDataSourcePermissionInfo)[datasourceId];
26+
const user = useSelector(getUser);
2527

2628
useEffect(() => {
2729
dispatch(fetchDatasourcePermissions({ datasourceId: datasourceId }));
@@ -75,6 +77,8 @@ export const DatasourcePermissionDialog = (props: {
7577
{ label: trans("share.datasourceOwner"), value: PermissionRole.Owner },
7678
]}
7779
permissionItems={permissions}
80+
contextType="organization"
81+
organizationId={user.currentOrgId}
7882
viewBodyRender={(list) => {
7983
if (!permissionInfo) {
8084
return <StyledLoading size={18} />;

client/packages/lowcoder/src/components/PermissionDialog/Permission.tsx

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { EmptyContent } from "pages/common/styledComponent";
2727
import { trans } from "i18n";
2828
import { PermissionItem } from "./PermissionList";
2929
import { currentApplication } from "@lowcoder-ee/redux/selectors/applicationSelector";
30-
import { fetchAvailableGroupsMembers } from "@lowcoder-ee/util/pagination/axios";
30+
import { fetchAvailableGroupsMembers, fetchAvailableOrgGroupsMembers } from "@lowcoder-ee/util/pagination/axios";
3131

3232
const AddAppUserContent = styled.div`
3333
display: flex;
@@ -186,6 +186,13 @@ const AddRoleSelect = styled(StyledRoleSelect)<{ $isVisible: boolean }>`
186186
display: ${(props) => (props.$isVisible ? "unset" : "none")};
187187
`;
188188

189+
type PermissionContextType = "application" | "organization";
190+
191+
type PermissionContextProps = {
192+
contextType: PermissionContextType;
193+
organizationId?: string;
194+
};
195+
189196
type AddAppOptionView = {
190197
type: ApplicationPermissionType;
191198
id: string;
@@ -294,8 +301,10 @@ const PermissionSelector = (props: {
294301
user: User;
295302
filterItems: PermissionItem[];
296303
supportRoles: { label: string; value: PermissionRole }[];
304+
contextType: PermissionContextType;
305+
organizationId?: string;
297306
}) => {
298-
const { selectedItems, setSelectRole, setSelectedItems, user } = props;
307+
const { selectedItems, setSelectRole, setSelectedItems, user, contextType, organizationId } = props;
299308
const [roleSelectVisible, setRoleSelectVisible] = useState(false);
300309
const selectRef = useRef<HTMLDivElement>(null);
301310
const [optionViews, setOptionViews] = useState<AddAppOptionView[]>()
@@ -305,42 +314,41 @@ const PermissionSelector = (props: {
305314

306315
const debouncedUserSearch = useCallback(
307316
debounce((searchTerm: string) => {
308-
if (!application) return;
309-
310317
setIsLoading(true);
311-
fetchAvailableGroupsMembers(application.applicationId, searchTerm).then(res => {
312-
if(res.success) {
313-
setOptionViews(getPermissionOptionView(res.data, props.filterItems))
314-
}
315-
setIsLoading(false);
316-
}).catch(() => {
318+
319+
if (contextType === "application" && application) {
320+
fetchAvailableGroupsMembers(application.applicationId, searchTerm).then(res => {
321+
if(res.success) {
322+
setOptionViews(getPermissionOptionView(res.data, props.filterItems))
323+
}
324+
setIsLoading(false);
325+
}).catch(() => {
326+
setIsLoading(false);
327+
});
328+
} else if (contextType === "organization" && organizationId) {
329+
fetchAvailableOrgGroupsMembers(organizationId, searchTerm).then(res => {
330+
if(res.success) {
331+
setOptionViews(getPermissionOptionView(res.data || [], props.filterItems))
332+
}
333+
setIsLoading(false);
334+
}).catch(() => {
335+
setIsLoading(false);
336+
});
337+
} else {
317338
setIsLoading(false);
318-
});
339+
}
319340
}, 500),
320-
[application, props.filterItems]
341+
[application, props.filterItems, contextType, organizationId]
321342
);
322343

323344
useEffect(() => {
324345
debouncedUserSearch(searchValue);
325-
326346
return () => {
327347
debouncedUserSearch.cancel();
328348
};
329349
}, [searchValue, debouncedUserSearch]);
330350

331-
useEffect(() => {
332-
if (!application) return;
333-
334-
setIsLoading(true);
335-
fetchAvailableGroupsMembers(application.applicationId, "").then(res => {
336-
if(res.success) {
337-
setOptionViews(getPermissionOptionView(res.data, props.filterItems))
338-
}
339-
setIsLoading(false);
340-
}).catch(() => {
341-
setIsLoading(false);
342-
});
343-
}, [application, props.filterItems]);
351+
344352

345353
useEffect(() => {
346354
setRoleSelectVisible(selectedItems.length > 0);
@@ -425,8 +433,8 @@ export const Permission = (props: {
425433
supportRoles: { label: string; value: PermissionRole }[];
426434
onCancel: () => void;
427435
addPermission: (userIds: string[], groupIds: string[], role: string) => void;
428-
}) => {
429-
const { onCancel } = props;
436+
} & PermissionContextProps) => {
437+
const { onCancel, contextType = "application", organizationId } = props;
430438
const user = useSelector(getUser);
431439
const [selectRole, setSelectRole] = useState<ApplicationRoleType>("viewer");
432440
const [selectedItems, setSelectedItems] = useState<PermissionAddEntity[]>([]);
@@ -443,6 +451,8 @@ export const Permission = (props: {
443451
user={user}
444452
filterItems={props.filterItems}
445453
supportRoles={props.supportRoles}
454+
contextType={contextType}
455+
organizationId={organizationId}
446456
/>
447457
<BottomButton>
448458
<TacoButton style={{ marginRight: "8px" }} onClick={onCancel}>

client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ export const PermissionDialog = (props: {
5757
) => void;
5858
updatePermission: (permissionId: string, role: string) => void;
5959
deletePermission: (permissionId: string) => void;
60+
contextType?: "application" | "organization";
61+
organizationId?: string;
6062
}) => {
61-
const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender } =
63+
const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender, contextType, organizationId } =
6264
props;
6365
const [activeStepKey, setActiveStepKey] = useState("view");
6466

@@ -117,6 +119,8 @@ export const PermissionDialog = (props: {
117119
addPermission={(userIds, groupIds, role) =>
118120
addPermission(userIds, groupIds, role, props.back)
119121
}
122+
contextType={contextType || "application"}
123+
organizationId={organizationId}
120124
/>
121125
),
122126
footerRender: (props) => null,

client/packages/lowcoder/src/util/pagination/axios.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,60 @@ export const fetchAvailableGroupsMembers = async (applicationId: string, search:
118118
}
119119
}
120120

121+
export const fetchAvailableOrgGroupsMembers = async (orgId: string, search: string = "") => {
122+
try {
123+
124+
125+
// Fetch org members and groups in parallel
126+
const [orgMembersResponse, groupsResponse] = await Promise.all([
127+
OrgApi.fetchOrgUsers(orgId),
128+
OrgApi.fetchGroup()
129+
]);
130+
131+
const orgMembers = orgMembersResponse.data.data.members || [];
132+
const groups = groupsResponse.data.data || [];
133+
134+
// Transform to the same format as application groups/members
135+
const transformedData = [
136+
// Add groups
137+
...groups.map((group: any) => ({
138+
type: "Group",
139+
data: {
140+
groupId: group.groupId,
141+
groupName: group.groupName,
142+
}
143+
})),
144+
// Add users
145+
...orgMembers.map((member: any) => ({
146+
type: "User",
147+
data: {
148+
userId: member.userId,
149+
name: member.name,
150+
avatarUrl: member.avatarUrl,
151+
}
152+
}))
153+
];
154+
155+
// Filter by search term if provided
156+
const filteredData = search ?
157+
transformedData.filter((item: any) => {
158+
const name = item.type === "Group" ? item.data.groupName : item.data.name;
159+
return name.toLowerCase().includes(search.toLowerCase());
160+
}) : transformedData;
161+
162+
return {
163+
success: true,
164+
data: filteredData
165+
};
166+
} catch (error: any) {
167+
console.error('Failed to fetch org data: ', error);
168+
return {
169+
success: false,
170+
error: error
171+
};
172+
}
173+
}
174+
121175
export const fetchOrgUsrPagination = async (request: fetchOrgUserRequestType)=> {
122176
try {
123177
const response = await OrgApi.fetchOrgUsersPagination(request);

0 commit comments

Comments
 (0)