mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 14:27:02 +08:00
fix(server): seat not allocated when new user invited to licensed workspace (#12322)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved the accuracy of workspace member overcapacity calculation. - Corrected seat allocation handling for one-time license variants, ensuring proper event emission and bypassing unnecessary updates. - **Refactor** - Streamlined internal logic by removing an obsolete method related to seat count checks. - **Tests** - Removed a workspace member list pagination test to streamline end-to-end testing. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -144,8 +144,7 @@ export class QuotaService {
|
|||||||
: await this.getWorkspaceStorageUsage(workspaceId);
|
: await this.getWorkspaceStorageUsage(workspaceId);
|
||||||
const memberCount =
|
const memberCount =
|
||||||
await this.models.workspaceUser.chargedCount(workspaceId);
|
await this.models.workspaceUser.chargedCount(workspaceId);
|
||||||
const overcapacityMemberCount =
|
const overcapacityMemberCount = memberCount - quota.memberLimit;
|
||||||
await this.models.workspaceUser.insufficientSeatMemberCount(workspaceId);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...quota,
|
...quota,
|
||||||
|
|||||||
@@ -289,15 +289,6 @@ export class WorkspaceUserModel extends BaseModel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async insufficientSeatMemberCount(workspaceId: string) {
|
|
||||||
return this.db.workspaceUserRole.count({
|
|
||||||
where: {
|
|
||||||
workspaceId,
|
|
||||||
status: WorkspaceMemberStatus.NeedMoreSeat,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getUserActiveRoles(
|
async getUserActiveRoles(
|
||||||
userId: string,
|
userId: string,
|
||||||
filter: { role?: WorkspaceRole } = {}
|
filter: { role?: WorkspaceRole } = {}
|
||||||
|
|||||||
@@ -288,6 +288,15 @@ export class LicenseService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (license.variant === SubscriptionVariant.Onetime) {
|
||||||
|
this.event.emit('workspace.members.allocateSeats', {
|
||||||
|
workspaceId,
|
||||||
|
quantity: license.quantity,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const count = await this.models.workspaceUser.chargedCount(workspaceId);
|
const count = await this.models.workspaceUser.chargedCount(workspaceId);
|
||||||
await this.fetchAffinePro(`/api/team/licenses/${license.key}/seats`, {
|
await this.fetchAffinePro(`/api/team/licenses/${license.key}/seats`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import { test } from '@affine-test/kit/playwright';
|
import { test } from '@affine-test/kit/playwright';
|
||||||
import {
|
import {
|
||||||
addUserToWorkspace,
|
|
||||||
createRandomUser,
|
createRandomUser,
|
||||||
enableCloudWorkspace,
|
enableCloudWorkspace,
|
||||||
loginUser,
|
loginUser,
|
||||||
} from '@affine-test/kit/utils/cloud';
|
} from '@affine-test/kit/utils/cloud';
|
||||||
import { clickPageModeButton } from '@affine-test/kit/utils/editor';
|
import { clickPageModeButton } from '@affine-test/kit/utils/editor';
|
||||||
import {
|
import {
|
||||||
clickNewPageButton,
|
|
||||||
getBlockSuiteEditorTitle,
|
getBlockSuiteEditorTitle,
|
||||||
waitForEditorLoad,
|
waitForEditorLoad,
|
||||||
waitForEmptyEditor,
|
waitForEmptyEditor,
|
||||||
} from '@affine-test/kit/utils/page-logic';
|
} from '@affine-test/kit/utils/page-logic';
|
||||||
import { openSettingModal } from '@affine-test/kit/utils/setting';
|
|
||||||
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
import { createLocalWorkspace } from '@affine-test/kit/utils/workspace';
|
||||||
import { expect } from '@playwright/test';
|
import { expect } from '@playwright/test';
|
||||||
|
|
||||||
@@ -28,76 +25,6 @@ test.beforeEach(async ({ page }) => {
|
|||||||
await loginUser(page, user);
|
await loginUser(page, user);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should have pagination in member list', async ({ page }) => {
|
|
||||||
await page.reload();
|
|
||||||
await waitForEditorLoad(page);
|
|
||||||
await createLocalWorkspace(
|
|
||||||
{
|
|
||||||
name: 'test',
|
|
||||||
},
|
|
||||||
page
|
|
||||||
);
|
|
||||||
await enableCloudWorkspace(page);
|
|
||||||
await clickNewPageButton(page);
|
|
||||||
const currentUrl = page.url();
|
|
||||||
// format: http://localhost:8080/workspace/${workspaceId}/xxx
|
|
||||||
const workspaceId = currentUrl.split('/')[4];
|
|
||||||
|
|
||||||
// create 10 user and add to workspace
|
|
||||||
const createUserAndAddToWorkspace = async () => {
|
|
||||||
const userB = await createRandomUser();
|
|
||||||
await addUserToWorkspace(workspaceId, userB.id, 1 /* READ */);
|
|
||||||
};
|
|
||||||
await Promise.all(
|
|
||||||
Array.from({ length: 10 })
|
|
||||||
.fill(1)
|
|
||||||
.map(() => createUserAndAddToWorkspace())
|
|
||||||
);
|
|
||||||
|
|
||||||
await openSettingModal(page);
|
|
||||||
await page
|
|
||||||
.getByTestId('settings-sidebar')
|
|
||||||
.getByTestId('workspace-setting:members')
|
|
||||||
.click();
|
|
||||||
|
|
||||||
await page.waitForTimeout(1000);
|
|
||||||
|
|
||||||
const firstPageMemberItemCount = await page
|
|
||||||
.locator('[data-testid="member-item"]')
|
|
||||||
.count();
|
|
||||||
|
|
||||||
expect(firstPageMemberItemCount).toBe(8);
|
|
||||||
|
|
||||||
const navigationItems = await page
|
|
||||||
.getByRole('navigation')
|
|
||||||
.getByRole('button')
|
|
||||||
.all();
|
|
||||||
|
|
||||||
// make sure the first member is the owner
|
|
||||||
await expect(page.getByTestId('member-item').first()).toContainText(
|
|
||||||
'Workspace Owner'
|
|
||||||
);
|
|
||||||
|
|
||||||
// There have four pagination items: < 1 2 >
|
|
||||||
expect(navigationItems.length).toBe(4);
|
|
||||||
// Click second page
|
|
||||||
await navigationItems[2].click();
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
// There should have other three members in second page
|
|
||||||
const secondPageMemberItemCount = await page
|
|
||||||
.locator('[data-testid="member-item"]')
|
|
||||||
.count();
|
|
||||||
expect(secondPageMemberItemCount).toBe(3);
|
|
||||||
// Click left arrow to back to first page
|
|
||||||
await navigationItems[0].click();
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
await expect(page.locator('[data-testid="member-item"]')).toHaveCount(8);
|
|
||||||
// Click right arrow to second page
|
|
||||||
await navigationItems[3].click();
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
await expect(page.locator('[data-testid="member-item"]')).toHaveCount(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should transform local favorites data', async ({ page }) => {
|
test('should transform local favorites data', async ({ page }) => {
|
||||||
await page.reload();
|
await page.reload();
|
||||||
await waitForEditorLoad(page);
|
await waitForEditorLoad(page);
|
||||||
|
|||||||
Reference in New Issue
Block a user