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:
parent
02742c3c76
commit
b6d17853d8
@ -1,6 +1,13 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Card, Row, Col, Tabs, Divider } from 'antd';
|
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 { ISchema, Schema } from '@formily/react';
|
||||||
import { RolesMenu } from './RolesMenu';
|
import { RolesMenu } from './RolesMenu';
|
||||||
import { useACLTranslation } from './locale';
|
import { useACLTranslation } from './locale';
|
||||||
@ -58,53 +65,56 @@ export const RolesManagement: React.FC = () => {
|
|||||||
children: item.Component ? React.createElement(item.Component, { active: activeKey === name }) : null,
|
children: item.Component ? React.createElement(item.Component, { active: activeKey === name }) : null,
|
||||||
}));
|
}));
|
||||||
const [role, setRole] = useState(null);
|
const [role, setRole] = useState(null);
|
||||||
|
const scCtx = useSchemaComponentContext();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RolesManagerContext.Provider value={{ role, setRole }}>
|
<SchemaComponentContext.Provider value={{ ...scCtx, designable: false }}>
|
||||||
<Card>
|
<RolesManagerContext.Provider value={{ role, setRole }}>
|
||||||
<Row gutter={24} style={{ flexWrap: 'nowrap' }}>
|
<Card>
|
||||||
<Col flex="280px" style={{ borderRight: '1px solid #eee', minWidth: '250px' }}>
|
<Row gutter={24} style={{ flexWrap: 'nowrap' }}>
|
||||||
<ResourceActionProvider
|
<Col flex="280px" style={{ borderRight: '1px solid #eee', minWidth: '250px' }}>
|
||||||
collection={collection}
|
<ResourceActionProvider
|
||||||
request={{
|
collection={collection}
|
||||||
resource: 'roles',
|
request={{
|
||||||
action: 'list',
|
resource: 'roles',
|
||||||
params: {
|
action: 'list',
|
||||||
pagination: false,
|
params: {
|
||||||
filter: {
|
pagination: false,
|
||||||
'name.$ne': 'root',
|
filter: {
|
||||||
|
'name.$ne': 'root',
|
||||||
|
},
|
||||||
|
showAnonymous: true,
|
||||||
|
sort: ['createdAt'],
|
||||||
|
appends: [],
|
||||||
},
|
},
|
||||||
showAnonymous: true,
|
}}
|
||||||
sort: ['createdAt'],
|
>
|
||||||
appends: [],
|
<CollectionProvider_deprecated collection={collection}>
|
||||||
},
|
<Row>
|
||||||
}}
|
<NewRole />
|
||||||
>
|
</Row>
|
||||||
<CollectionProvider_deprecated collection={collection}>
|
<Divider style={{ margin: '12px 0' }} />
|
||||||
<Row>
|
<RolesMenu />
|
||||||
<NewRole />
|
</CollectionProvider_deprecated>
|
||||||
</Row>
|
</ResourceActionProvider>
|
||||||
<Divider style={{ margin: '12px 0' }} />
|
</Col>
|
||||||
<RolesMenu />
|
<Col flex="auto" style={{ overflow: 'hidden' }}>
|
||||||
</CollectionProvider_deprecated>
|
<Tabs
|
||||||
</ResourceActionProvider>
|
activeKey={activeKey}
|
||||||
</Col>
|
onChange={(key) => setActiveKey(key)}
|
||||||
<Col flex="auto" style={{ overflow: 'hidden' }}>
|
items={[
|
||||||
<Tabs
|
{
|
||||||
activeKey={activeKey}
|
key: 'permissions',
|
||||||
onChange={(key) => setActiveKey(key)}
|
label: t('Permissions'),
|
||||||
items={[
|
children: <Permissions active={activeKey === 'permissions'} />,
|
||||||
{
|
},
|
||||||
key: 'permissions',
|
...tabs,
|
||||||
label: t('Permissions'),
|
]}
|
||||||
children: <Permissions active={activeKey === 'permissions'} />,
|
/>
|
||||||
},
|
</Col>
|
||||||
...tabs,
|
</Row>
|
||||||
]}
|
</Card>
|
||||||
/>
|
</RolesManagerContext.Provider>
|
||||||
</Col>
|
</SchemaComponentContext.Provider>
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
</RolesManagerContext.Provider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
@ -25,19 +25,21 @@ export const listExcludeRole = async (ctx: Context, next: Next) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const userIds = users.map((user: { id: number }) => user.id);
|
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({
|
const [rows, count] = await repo.findAndCount({
|
||||||
context: ctx,
|
context: ctx,
|
||||||
offset: (page - 1) * pageSize,
|
offset: (page - 1) * pageSize,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
// Ensure memberIds is not empty to resolve strange issue:
|
filter,
|
||||||
// notIn: [] will be translated to "WHERE id IS NULL"
|
|
||||||
filter: userIds.length
|
|
||||||
? {
|
|
||||||
id: {
|
|
||||||
$notIn: userIds,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
: {},
|
|
||||||
});
|
});
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
count,
|
count,
|
||||||
|
Loading…
Reference in New Issue
Block a user