fix(acl): bug of user filtering when adding them to roles (#3754)

* fix(acl): bug of user filtering when adding them to roles

* chore: add tests
This commit is contained in:
YANG QIA 2024-03-19 17:53:13 +08:00 committed by GitHub
parent 02742c3c76
commit b6d17853d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 123 additions and 55 deletions

View File

@ -1,6 +1,13 @@
import React, { useState } from 'react';
import { Card, Row, Col, Tabs, Divider } from 'antd';
import { CollectionProvider, CollectionProvider_deprecated, ResourceActionProvider, usePlugin } from '@nocobase/client';
import {
CollectionProvider,
CollectionProvider_deprecated,
ResourceActionProvider,
SchemaComponentContext,
usePlugin,
useSchemaComponentContext,
} from '@nocobase/client';
import { ISchema, Schema } from '@formily/react';
import { RolesMenu } from './RolesMenu';
import { useACLTranslation } from './locale';
@ -58,53 +65,56 @@ export const RolesManagement: React.FC = () => {
children: item.Component ? React.createElement(item.Component, { active: activeKey === name }) : null,
}));
const [role, setRole] = useState(null);
const scCtx = useSchemaComponentContext();
return (
<RolesManagerContext.Provider value={{ role, setRole }}>
<Card>
<Row gutter={24} style={{ flexWrap: 'nowrap' }}>
<Col flex="280px" style={{ borderRight: '1px solid #eee', minWidth: '250px' }}>
<ResourceActionProvider
collection={collection}
request={{
resource: 'roles',
action: 'list',
params: {
pagination: false,
filter: {
'name.$ne': 'root',
<SchemaComponentContext.Provider value={{ ...scCtx, designable: false }}>
<RolesManagerContext.Provider value={{ role, setRole }}>
<Card>
<Row gutter={24} style={{ flexWrap: 'nowrap' }}>
<Col flex="280px" style={{ borderRight: '1px solid #eee', minWidth: '250px' }}>
<ResourceActionProvider
collection={collection}
request={{
resource: 'roles',
action: 'list',
params: {
pagination: false,
filter: {
'name.$ne': 'root',
},
showAnonymous: true,
sort: ['createdAt'],
appends: [],
},
showAnonymous: true,
sort: ['createdAt'],
appends: [],
},
}}
>
<CollectionProvider_deprecated collection={collection}>
<Row>
<NewRole />
</Row>
<Divider style={{ margin: '12px 0' }} />
<RolesMenu />
</CollectionProvider_deprecated>
</ResourceActionProvider>
</Col>
<Col flex="auto" style={{ overflow: 'hidden' }}>
<Tabs
activeKey={activeKey}
onChange={(key) => setActiveKey(key)}
items={[
{
key: 'permissions',
label: t('Permissions'),
children: <Permissions active={activeKey === 'permissions'} />,
},
...tabs,
]}
/>
</Col>
</Row>
</Card>
</RolesManagerContext.Provider>
}}
>
<CollectionProvider_deprecated collection={collection}>
<Row>
<NewRole />
</Row>
<Divider style={{ margin: '12px 0' }} />
<RolesMenu />
</CollectionProvider_deprecated>
</ResourceActionProvider>
</Col>
<Col flex="auto" style={{ overflow: 'hidden' }}>
<Tabs
activeKey={activeKey}
onChange={(key) => setActiveKey(key)}
items={[
{
key: 'permissions',
label: t('Permissions'),
children: <Permissions active={activeKey === 'permissions'} />,
},
...tabs,
]}
/>
</Col>
</Row>
</Card>
</RolesManagerContext.Provider>
</SchemaComponentContext.Provider>
);
};

View File

@ -0,0 +1,56 @@
import { Database, Repository } from '@nocobase/database';
import { MockServer, createMockServer } from '@nocobase/test';
describe('actions', () => {
let app: MockServer;
let db: Database;
let repo: Repository;
let agent: any;
beforeAll(async () => {
app = await createMockServer({
plugins: ['acl', 'users', 'data-source-manager'],
});
db = app.db;
repo = db.getRepository('users');
agent = app.agent();
});
afterAll(async () => {
await app.destroy();
});
it('should list users exclude role', async () => {
const res = await agent.resource('users').listExcludeRole({
roleName: ['admin'],
});
expect(res.status).toBe(200);
expect(res.body.data.length).toBe(0);
});
it('should list users exclude role with filter', async () => {
let res = await agent.resource('users').listExcludeRole({
roleName: ['test'],
});
expect(res.status).toBe(200);
expect(res.body.data.length).toBe(1);
res = await agent.resource('users').listExcludeRole({
roleName: ['test'],
filter: {
id: 1,
},
});
expect(res.status).toBe(200);
expect(res.body.data.length).toBe(1);
res = await agent.resource('users').listExcludeRole({
roleName: ['test'],
filter: {
id: 2,
},
});
expect(res.status).toBe(200);
expect(res.body.data.length).toBe(0);
});
});

View File

@ -25,19 +25,21 @@ export const listExcludeRole = async (ctx: Context, next: Next) => {
},
});
const userIds = users.map((user: { id: number }) => user.id);
if (userIds.length) {
ctx.action.mergeParams({
filter: {
id: {
$notIn: userIds,
},
},
});
}
const { filter } = ctx.action.params;
const [rows, count] = await repo.findAndCount({
context: ctx,
offset: (page - 1) * pageSize,
limit: pageSize,
// Ensure memberIds is not empty to resolve strange issue:
// notIn: [] will be translated to "WHERE id IS NULL"
filter: userIds.length
? {
id: {
$notIn: userIds,
},
}
: {},
filter,
});
ctx.body = {
count,