mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-20 19:46:32 +08:00
refactor(server): permission (#10449)
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
import Sinon from 'sinon';
|
||||
|
||||
import { EventBus } from '../../base';
|
||||
import { DocRole, Models } from '../../models';
|
||||
import { createTestingModule, TestingModule } from '../utils';
|
||||
|
||||
let db: PrismaClient;
|
||||
let models: Models;
|
||||
let module: TestingModule;
|
||||
|
||||
test.before(async () => {
|
||||
module = await createTestingModule({
|
||||
tapModule: m => {
|
||||
m.overrideProvider(EventBus).useValue(Sinon.createStubInstance(EventBus));
|
||||
},
|
||||
});
|
||||
models = module.get(Models);
|
||||
db = module.get(PrismaClient);
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await module.initTestingDB();
|
||||
Sinon.reset();
|
||||
});
|
||||
|
||||
test.after(async () => {
|
||||
await module.close();
|
||||
});
|
||||
|
||||
async function create() {
|
||||
return db.workspace.create({
|
||||
data: { public: false },
|
||||
});
|
||||
}
|
||||
|
||||
test('should set doc owner', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
const docId = 'fake-doc-id';
|
||||
|
||||
await models.docUser.setOwner(workspace.id, docId, user.id);
|
||||
const role = await models.docUser.get(workspace.id, docId, user.id);
|
||||
|
||||
t.is(role?.type, DocRole.Owner);
|
||||
});
|
||||
|
||||
test('should transfer doc owner', async t => {
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
const user2 = await models.user.create({ email: 'u2@affine.pro' });
|
||||
const workspace = await create();
|
||||
const docId = 'fake-doc-id';
|
||||
|
||||
await models.docUser.setOwner(workspace.id, docId, user.id);
|
||||
await models.docUser.setOwner(workspace.id, docId, user2.id);
|
||||
|
||||
const oldOwnerRole = await models.docUser.get(workspace.id, docId, user.id);
|
||||
const newOwnerRole = await models.docUser.get(workspace.id, docId, user2.id);
|
||||
|
||||
t.is(oldOwnerRole?.type, DocRole.Manager);
|
||||
t.is(newOwnerRole?.type, DocRole.Owner);
|
||||
});
|
||||
|
||||
test('should set doc user role', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
const docId = 'fake-doc-id';
|
||||
|
||||
await models.docUser.set(workspace.id, docId, user.id, DocRole.Manager);
|
||||
const role = await models.docUser.get(workspace.id, docId, user.id);
|
||||
|
||||
t.is(role?.type, DocRole.Manager);
|
||||
});
|
||||
|
||||
test('should not allow setting doc owner through setDocUserRole', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
const docId = 'fake-doc-id';
|
||||
|
||||
await t.throwsAsync(
|
||||
models.docUser.set(workspace.id, docId, user.id, DocRole.Owner),
|
||||
{ message: 'Cannot set Owner role of a doc to a user.' }
|
||||
);
|
||||
});
|
||||
|
||||
test('should delete doc user role', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
const docId = 'fake-doc-id';
|
||||
|
||||
await models.docUser.set(workspace.id, docId, user.id, DocRole.Manager);
|
||||
await models.docUser.delete(workspace.id, docId, user.id);
|
||||
|
||||
const role = await models.docUser.get(workspace.id, docId, user.id);
|
||||
t.is(role, null);
|
||||
});
|
||||
|
||||
test('should paginate doc user roles', async t => {
|
||||
const workspace = await create();
|
||||
const docId = 'fake-doc-id';
|
||||
await db.user.createMany({
|
||||
data: Array.from({ length: 200 }, (_, i) => ({
|
||||
id: String(i),
|
||||
name: `u${i}`,
|
||||
email: `${i}@affine.pro`,
|
||||
})),
|
||||
});
|
||||
|
||||
await db.workspaceDocUserRole.createMany({
|
||||
data: Array.from({ length: 200 }, (_, i) => ({
|
||||
workspaceId: workspace.id,
|
||||
docId,
|
||||
userId: String(i),
|
||||
type: DocRole.Editor,
|
||||
createdAt: new Date(Date.now() + i * 1000),
|
||||
})),
|
||||
});
|
||||
|
||||
const [roles, total] = await models.docUser.paginate(workspace.id, docId, {
|
||||
first: 10,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
t.is(roles.length, 10);
|
||||
t.is(total, 200);
|
||||
|
||||
const [roles2] = await models.docUser.paginate(workspace.id, docId, {
|
||||
after: roles.at(-1)?.createdAt.toISOString(),
|
||||
first: 50,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
t.is(roles2.length, 50);
|
||||
t.not(roles2[0].type, DocRole.Owner);
|
||||
t.deepEqual(
|
||||
roles2.map(r => r.userId),
|
||||
roles2
|
||||
.toSorted((a, b) => a.createdAt.getTime() - b.createdAt.getTime())
|
||||
.map(r => r.userId)
|
||||
);
|
||||
});
|
||||
|
||||
test('should count doc user roles', async t => {
|
||||
const workspace = await create();
|
||||
const docId = 'fake-doc-id';
|
||||
const users = await Promise.all([
|
||||
models.user.create({ email: 'u1@affine.pro' }),
|
||||
models.user.create({ email: 'u2@affine.pro' }),
|
||||
]);
|
||||
|
||||
await Promise.all(
|
||||
users.map(user =>
|
||||
models.docUser.set(workspace.id, docId, user.id, DocRole.Manager)
|
||||
)
|
||||
);
|
||||
|
||||
const count = await models.docUser.count(workspace.id, docId);
|
||||
t.is(count, 2);
|
||||
});
|
||||
@@ -1,232 +0,0 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import ava, { TestFn } from 'ava';
|
||||
|
||||
import { Config } from '../../base/config';
|
||||
import { WorkspaceRole } from '../../core/permission';
|
||||
import { PublicPageMode } from '../../models/common';
|
||||
import { PageModel } from '../../models/page';
|
||||
import { type User, UserModel } from '../../models/user';
|
||||
import { type Workspace, WorkspaceModel } from '../../models/workspace';
|
||||
import { createTestingModule, type TestingModule } from '../utils';
|
||||
|
||||
interface Context {
|
||||
config: Config;
|
||||
module: TestingModule;
|
||||
db: PrismaClient;
|
||||
user: UserModel;
|
||||
workspace: WorkspaceModel;
|
||||
page: PageModel;
|
||||
}
|
||||
|
||||
const test = ava as TestFn<Context>;
|
||||
|
||||
test.before(async t => {
|
||||
const module = await createTestingModule();
|
||||
|
||||
t.context.user = module.get(UserModel);
|
||||
t.context.workspace = module.get(WorkspaceModel);
|
||||
t.context.page = module.get(PageModel);
|
||||
t.context.db = module.get(PrismaClient);
|
||||
t.context.config = module.get(Config);
|
||||
t.context.module = module;
|
||||
});
|
||||
|
||||
let user: User;
|
||||
let workspace: Workspace;
|
||||
|
||||
test.beforeEach(async t => {
|
||||
await t.context.module.initTestingDB();
|
||||
user = await t.context.user.create({
|
||||
email: 'test@affine.pro',
|
||||
});
|
||||
workspace = await t.context.workspace.create(user.id);
|
||||
});
|
||||
|
||||
test.after(async t => {
|
||||
await t.context.module.close();
|
||||
});
|
||||
|
||||
test('should create page with default mode and public false', async t => {
|
||||
const page = await t.context.page.upsert(workspace.id, 'page1');
|
||||
t.is(page.workspaceId, workspace.id);
|
||||
t.is(page.docId, 'page1');
|
||||
t.is(page.mode, PublicPageMode.Page);
|
||||
t.is(page.public, false);
|
||||
});
|
||||
|
||||
test('should update page', async t => {
|
||||
const page = await t.context.page.upsert(workspace.id, 'page1');
|
||||
const data = {
|
||||
mode: PublicPageMode.Edgeless,
|
||||
public: true,
|
||||
};
|
||||
await t.context.page.upsert(workspace.id, 'page1', data);
|
||||
const page1 = await t.context.page.get(workspace.id, 'page1');
|
||||
t.deepEqual(page1, {
|
||||
...page,
|
||||
...data,
|
||||
});
|
||||
});
|
||||
|
||||
test('should get null when page not exists', async t => {
|
||||
const page = await t.context.page.get(workspace.id, 'page1');
|
||||
t.is(page, null);
|
||||
});
|
||||
|
||||
test('should get page by id and public flag', async t => {
|
||||
await t.context.page.upsert(workspace.id, 'page1');
|
||||
await t.context.page.upsert(workspace.id, 'page2', {
|
||||
public: true,
|
||||
});
|
||||
let page1 = await t.context.page.get(workspace.id, 'page1');
|
||||
t.is(page1!.public, false);
|
||||
page1 = await t.context.page.get(workspace.id, 'page1', true);
|
||||
t.is(page1, null);
|
||||
let page2 = await t.context.page.get(workspace.id, 'page2', true);
|
||||
t.is(page2!.public, true);
|
||||
page2 = await t.context.page.get(workspace.id, 'page2', false);
|
||||
t.is(page2, null);
|
||||
});
|
||||
|
||||
test('should get public page count', async t => {
|
||||
await t.context.page.upsert(workspace.id, 'page1', {
|
||||
public: true,
|
||||
});
|
||||
await t.context.page.upsert(workspace.id, 'page2', {
|
||||
public: true,
|
||||
});
|
||||
await t.context.page.upsert(workspace.id, 'page3');
|
||||
const count = await t.context.page.getPublicsCount(workspace.id);
|
||||
t.is(count, 2);
|
||||
});
|
||||
|
||||
test('should get public pages of a workspace', async t => {
|
||||
await t.context.page.upsert(workspace.id, 'page1', {
|
||||
public: true,
|
||||
});
|
||||
await t.context.page.upsert(workspace.id, 'page2', {
|
||||
public: true,
|
||||
});
|
||||
await t.context.page.upsert(workspace.id, 'page3');
|
||||
const pages = await t.context.page.findPublics(workspace.id);
|
||||
t.is(pages.length, 2);
|
||||
t.deepEqual(pages.map(p => p.docId).sort(), ['page1', 'page2']);
|
||||
});
|
||||
|
||||
test('should grant a member to access a page', async t => {
|
||||
await t.context.page.upsert(workspace.id, 'page1', {
|
||||
public: true,
|
||||
});
|
||||
const member = await t.context.user.create({
|
||||
email: 'test1@affine.pro',
|
||||
});
|
||||
await t.context.page.grantMember(workspace.id, 'page1', member.id);
|
||||
let hasAccess = await t.context.page.isMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
member.id
|
||||
);
|
||||
t.true(hasAccess);
|
||||
hasAccess = await t.context.page.isMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Collaborator
|
||||
);
|
||||
t.false(hasAccess);
|
||||
// grant write permission
|
||||
await t.context.page.grantMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Collaborator
|
||||
);
|
||||
hasAccess = await t.context.page.isMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Collaborator
|
||||
);
|
||||
t.true(hasAccess);
|
||||
hasAccess = await t.context.page.isMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Collaborator
|
||||
);
|
||||
t.true(hasAccess);
|
||||
// delete member
|
||||
const count = await t.context.page.deleteMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id
|
||||
);
|
||||
t.is(count, 1);
|
||||
hasAccess = await t.context.page.isMember(workspace.id, 'page1', user.id);
|
||||
t.false(hasAccess);
|
||||
});
|
||||
|
||||
test('should change the page owner', async t => {
|
||||
await t.context.page.upsert(workspace.id, 'page1', {
|
||||
public: true,
|
||||
});
|
||||
await t.context.page.grantMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Owner
|
||||
);
|
||||
t.true(
|
||||
await t.context.page.isMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Owner
|
||||
)
|
||||
);
|
||||
|
||||
// change owner
|
||||
const otherUser = await t.context.user.create({
|
||||
email: 'test1@affine.pro',
|
||||
});
|
||||
await t.context.page.grantMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
otherUser.id,
|
||||
WorkspaceRole.Owner
|
||||
);
|
||||
t.true(
|
||||
await t.context.page.isMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
otherUser.id,
|
||||
WorkspaceRole.Owner
|
||||
)
|
||||
);
|
||||
t.false(
|
||||
await t.context.page.isMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Owner
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test('should not delete owner from page', async t => {
|
||||
await t.context.page.upsert(workspace.id, 'page1', {
|
||||
public: true,
|
||||
});
|
||||
await t.context.page.grantMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id,
|
||||
WorkspaceRole.Owner
|
||||
);
|
||||
const count = await t.context.page.deleteMember(
|
||||
workspace.id,
|
||||
'page1',
|
||||
user.id
|
||||
);
|
||||
t.is(count, 0);
|
||||
});
|
||||
@@ -2,13 +2,13 @@ import ava, { TestFn } from 'ava';
|
||||
import Sinon from 'sinon';
|
||||
|
||||
import { EmailAlreadyUsed, EventBus } from '../../base';
|
||||
import { WorkspaceRole } from '../../core/permission';
|
||||
import { Models } from '../../models';
|
||||
import { UserModel } from '../../models/user';
|
||||
import { WorkspaceMemberStatus } from '../../models/workspace';
|
||||
import { createTestingModule, sleep, type TestingModule } from '../utils';
|
||||
|
||||
interface Context {
|
||||
module: TestingModule;
|
||||
models: Models;
|
||||
user: UserModel;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ test.before(async t => {
|
||||
const module = await createTestingModule({});
|
||||
|
||||
t.context.user = module.get(UserModel);
|
||||
t.context.models = module.get(Models);
|
||||
t.context.module = module;
|
||||
});
|
||||
|
||||
@@ -253,24 +254,13 @@ test('should trigger user.deleted event', async t => {
|
||||
|
||||
const user = await t.context.user.create({
|
||||
email: 'test@affine.pro',
|
||||
workspacePermissions: {
|
||||
create: {
|
||||
workspace: {
|
||||
create: {
|
||||
id: 'test-workspace',
|
||||
public: false,
|
||||
},
|
||||
},
|
||||
type: WorkspaceRole.Owner,
|
||||
status: WorkspaceMemberStatus.Accepted,
|
||||
},
|
||||
},
|
||||
});
|
||||
const workspace = await t.context.models.workspace.create(user.id);
|
||||
|
||||
await t.context.user.delete(user.id);
|
||||
|
||||
t.true(
|
||||
spy.calledOnceWithExactly({ ...user, ownedWorkspaces: ['test-workspace'] })
|
||||
spy.calledOnceWithExactly({ ...user, ownedWorkspaces: [workspace.id] })
|
||||
);
|
||||
// await for 'user.deleted' event to be emitted and executed
|
||||
// avoid race condition cause database dead lock
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import test from 'ava';
|
||||
import Sinon from 'sinon';
|
||||
|
||||
import { EventBus } from '../../base';
|
||||
import { Models, WorkspaceMemberStatus, WorkspaceRole } from '../../models';
|
||||
import { createTestingModule, TestingModule } from '../utils';
|
||||
|
||||
let db: PrismaClient;
|
||||
let models: Models;
|
||||
let module: TestingModule;
|
||||
let event: Sinon.SinonStubbedInstance<EventBus>;
|
||||
|
||||
test.before(async () => {
|
||||
module = await createTestingModule({
|
||||
tapModule: m => {
|
||||
m.overrideProvider(EventBus).useValue(Sinon.createStubInstance(EventBus));
|
||||
},
|
||||
});
|
||||
models = module.get(Models);
|
||||
event = module.get(EventBus);
|
||||
db = module.get(PrismaClient);
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await module.initTestingDB();
|
||||
Sinon.reset();
|
||||
});
|
||||
|
||||
test.after(async () => {
|
||||
await module.close();
|
||||
});
|
||||
|
||||
async function create() {
|
||||
return db.workspace.create({
|
||||
data: { public: false },
|
||||
});
|
||||
}
|
||||
|
||||
test('should set workspace owner', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
await models.workspaceUser.setOwner(workspace.id, user.id);
|
||||
const owner = await models.workspaceUser.getOwner(workspace.id);
|
||||
|
||||
t.is(owner.id, user.id);
|
||||
});
|
||||
|
||||
test('should transfer workespace owner', async t => {
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
const user2 = await models.user.create({ email: 'u2@affine.pro' });
|
||||
const workspace = await models.workspace.create(user.id);
|
||||
|
||||
await models.workspaceUser.setOwner(workspace.id, user2.id);
|
||||
|
||||
t.true(
|
||||
event.emit.lastCall.calledWith('workspace.owner.changed', {
|
||||
workspaceId: workspace.id,
|
||||
from: user.id,
|
||||
to: user2.id,
|
||||
})
|
||||
);
|
||||
|
||||
const owner2 = await models.workspaceUser.getOwner(workspace.id);
|
||||
t.is(owner2.id, user2.id);
|
||||
});
|
||||
|
||||
test('should get user role', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
await models.workspaceUser.set(workspace.id, user.id, WorkspaceRole.Admin);
|
||||
|
||||
const role = await models.workspaceUser.get(workspace.id, user.id);
|
||||
|
||||
t.is(role!.type, WorkspaceRole.Admin);
|
||||
});
|
||||
|
||||
test('should get active workspace role', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
await models.workspaceUser.set(
|
||||
workspace.id,
|
||||
user.id,
|
||||
WorkspaceRole.Admin,
|
||||
WorkspaceMemberStatus.Accepted
|
||||
);
|
||||
|
||||
const role = await models.workspaceUser.getActive(workspace.id, user.id);
|
||||
|
||||
t.is(role!.type, WorkspaceRole.Admin);
|
||||
});
|
||||
|
||||
test('should not get inactive workspace role', async t => {
|
||||
const workspace = await create();
|
||||
|
||||
const u1 = await models.user.create({ email: 'u1@affine.pro' });
|
||||
|
||||
await models.workspaceUser.set(workspace.id, u1.id, WorkspaceRole.Admin);
|
||||
|
||||
let role = await models.workspaceUser.getActive(workspace.id, u1.id);
|
||||
t.is(role, null);
|
||||
|
||||
await models.workspaceUser.setStatus(
|
||||
workspace.id,
|
||||
u1.id,
|
||||
WorkspaceMemberStatus.UnderReview
|
||||
);
|
||||
|
||||
role = await models.workspaceUser.getActive(workspace.id, u1.id);
|
||||
t.is(role, null);
|
||||
});
|
||||
|
||||
test('should update user role', async t => {
|
||||
const workspace = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
await models.workspaceUser.set(
|
||||
workspace.id,
|
||||
user.id,
|
||||
WorkspaceRole.Admin,
|
||||
WorkspaceMemberStatus.Accepted
|
||||
);
|
||||
const role = await models.workspaceUser.get(workspace.id, user.id);
|
||||
|
||||
t.is(role!.type, WorkspaceRole.Admin);
|
||||
|
||||
await models.workspaceUser.set(
|
||||
workspace.id,
|
||||
user.id,
|
||||
WorkspaceRole.Collaborator
|
||||
);
|
||||
|
||||
const role2 = await models.workspaceUser.get(workspace.id, user.id);
|
||||
|
||||
t.is(role2!.type, WorkspaceRole.Collaborator);
|
||||
t.deepEqual(event.emit.lastCall.args, [
|
||||
'workspace.members.roleChanged',
|
||||
{
|
||||
userId: user.id,
|
||||
workspaceId: workspace.id,
|
||||
role: WorkspaceRole.Collaborator,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('should return workspace role if status is Accepted', async t => {
|
||||
const workspace = await create();
|
||||
const u1 = await models.user.create({ email: 'u1@affine.pro' });
|
||||
|
||||
await models.workspaceUser.set(workspace.id, u1.id, WorkspaceRole.Admin);
|
||||
await models.workspaceUser.setStatus(
|
||||
workspace.id,
|
||||
u1.id,
|
||||
WorkspaceMemberStatus.Accepted
|
||||
);
|
||||
const role = await models.workspaceUser.get(workspace.id, u1.id);
|
||||
|
||||
t.is(role!.type, WorkspaceRole.Admin);
|
||||
});
|
||||
|
||||
test('should delete workspace user role', async t => {
|
||||
const workspace = await create();
|
||||
const u1 = await models.user.create({ email: 'u1@affine.pro' });
|
||||
|
||||
await models.workspaceUser.set(workspace.id, u1.id, WorkspaceRole.Admin);
|
||||
await models.workspaceUser.setStatus(
|
||||
workspace.id,
|
||||
u1.id,
|
||||
WorkspaceMemberStatus.Accepted
|
||||
);
|
||||
|
||||
let role = await models.workspaceUser.get(workspace.id, u1.id);
|
||||
t.is(role!.type, WorkspaceRole.Admin);
|
||||
|
||||
await models.workspaceUser.delete(workspace.id, u1.id);
|
||||
|
||||
role = await models.workspaceUser.get(workspace.id, u1.id);
|
||||
t.is(role, null);
|
||||
});
|
||||
|
||||
test('should get user workspace roles with filter', async t => {
|
||||
const ws1 = await create();
|
||||
const ws2 = await create();
|
||||
const user = await models.user.create({ email: 'u1@affine.pro' });
|
||||
|
||||
await db.workspaceUserRole.createMany({
|
||||
data: [
|
||||
{
|
||||
workspaceId: ws1.id,
|
||||
userId: user.id,
|
||||
type: WorkspaceRole.Admin,
|
||||
status: WorkspaceMemberStatus.Accepted,
|
||||
},
|
||||
{
|
||||
workspaceId: ws2.id,
|
||||
userId: user.id,
|
||||
type: WorkspaceRole.Collaborator,
|
||||
status: WorkspaceMemberStatus.Accepted,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let roles = await models.workspaceUser.getUserActiveRoles(user.id, {
|
||||
role: WorkspaceRole.Admin,
|
||||
});
|
||||
t.is(roles.length, 1);
|
||||
t.is(roles[0].type, WorkspaceRole.Admin);
|
||||
|
||||
roles = await models.workspaceUser.getUserActiveRoles(user.id);
|
||||
t.is(roles.length, 2);
|
||||
});
|
||||
|
||||
test('should paginate workspace user roles', async t => {
|
||||
const workspace = await create();
|
||||
await db.user.createMany({
|
||||
data: Array.from({ length: 200 }, (_, i) => ({
|
||||
id: String(i),
|
||||
name: `u${i}`,
|
||||
email: `${i}@affine.pro`,
|
||||
})),
|
||||
});
|
||||
|
||||
await db.workspaceUserRole.createMany({
|
||||
data: Array.from({ length: 200 }, (_, i) => ({
|
||||
workspaceId: workspace.id,
|
||||
userId: String(i),
|
||||
type: WorkspaceRole.Collaborator,
|
||||
status: Object.values(WorkspaceMemberStatus)[
|
||||
Math.floor(Math.random() * Object.values(WorkspaceMemberStatus).length)
|
||||
],
|
||||
createdAt: new Date(Date.now() + i * 1000),
|
||||
})),
|
||||
});
|
||||
|
||||
const [roles, total] = await models.workspaceUser.paginate(workspace.id, {
|
||||
first: 10,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
t.is(roles.length, 10);
|
||||
t.is(total, 200);
|
||||
|
||||
const [roles2] = await models.workspaceUser.paginate(workspace.id, {
|
||||
after: roles.at(-1)?.createdAt.toISOString(),
|
||||
first: 50,
|
||||
offset: 0,
|
||||
});
|
||||
|
||||
t.is(roles2.length, 50);
|
||||
t.deepEqual(
|
||||
roles2.map(r => r.id),
|
||||
roles2
|
||||
.toSorted((a, b) => a.createdAt.getTime() - b.createdAt.getTime())
|
||||
.map(r => r.id)
|
||||
);
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user