Skip to content

feat: team onwer give - #7605

Open
shortlight5980 wants to merge 1 commit into
labring:mainfrom
shortlight5980:onwer-give
Open

feat: team onwer give#7605
shortlight5980 wants to merge 1 commit into
labring:mainfrom
shortlight5980:onwer-give

Conversation

@shortlight5980

Copy link
Copy Markdown
Collaborator

现在单团队只有企业微信可以转移
新增多团队的转移,转移时如果没有别的 onwer 团队就新建一个

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 34.63% 3495 / 10092
🔵 Statements 34.53% 3693 / 10693
🔵 Functions 29.23% 704 / 2408
🔵 Branches 29.24% 1763 / 6028
File CoverageNo changed files found.
Generated in workflow #3043 for commit a3a12e0 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

Build and publish successful - Preview fastgpt Image:

ghcr.io/labring/fastgpt-pr:fastgpt_a3a12e0d8dca8fa00af5f1b1f1935ba25e6028b5

🕒 Time: 2026-09-07 10:30:45 (UTC+8)

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

Admin Preview Image Ready!

ghcr.io/labring/fastgpt-pr:admin_a3a12e0d8dca8fa00af5f1b1f1935ba25e6028b5

🕒 Time: 2026-09-07 10:28:20 (UTC+8)

@shortlight5980
shortlight5980 force-pushed the onwer-give branch 2 times, most recently from e12f826 to da3b1b8 Compare August 26, 2026 10:06
@FinleyGe FinleyGe self-assigned this Aug 26, 2026
FinleyGe
FinleyGe previously approved these changes Aug 26, 2026
@shortlight5980
shortlight5980 force-pushed the onwer-give branch 2 times, most recently from 48969ef to d9541eb Compare August 27, 2026 06:27
@pull-request-size pull-request-size Bot added size/L and removed size/S labels Aug 27, 2026
@shortlight5980
shortlight5980 force-pushed the onwer-give branch 4 times, most recently from 6823fac to cd9c768 Compare August 31, 2026 03:15
@FinleyGe

Copy link
Copy Markdown
Collaborator

[P2] Preserve active membership when transferring ownership

The transaction validates the target member with status: active at pro/admin/src/service/support/user/team/controller/changeOwner.ts:46-49, but the role update at pro/admin/src/service/support/user/team/controller/changeOwner.ts:83-89 matches only { userId, teamId }. Since pro/admin/src/pages/api/support/user/team/member/updateInvite.ts:22-32 can concurrently change the same member to leave or forbidden without taking the team lock, this request can still set a non-active member as the team owner.

Please serialize member-status changes with the same team lock, and/or include status: active in this update predicate and fail the transaction when no row is matched. Add a regression test covering the status change between validation and the owner update.

@FinleyGe

FinleyGe commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

P1: The user lock is released before the outer Mongo transaction commits. In packages/service/support/user/team/controller.ts:153-157, createUserLoginTeam runs the fallback check and team creation inside withUserLock, but this function is called from the handler of passwordVerificationService.consumeInTransaction. That outer transaction commits only after the handler returns. Therefore, a second concurrent login with a different valid pre-login code can acquire the lock while the first team inserts are still uncommitted; its transaction cannot see the first team and can create another owner team for the same user. Please keep the lock around the whole transaction, or add a database-level idempotency/serialization guarantee, and add a concurrent-login regression test.

@FinleyGe

FinleyGe commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

P1: Sync mode ownership transfer can be bypassed through the API. In pro/admin/src/service/support/user/team/controller/changeOwner.ts:62-64, the backend rejects non-WeCom teams only when teamMode is single. The frontend hides the transfer action whenever isSyncMode is true (projects/app/src/pageComponents/account/team/MemberTable.tsx:236-238), but a current team owner can call the endpoint directly in sync mode and transfer ownership of a non-WeCom team. Please enforce the same mode restriction in the backend rather than relying on the UI, and add an API/service regression test for sync mode.

@shortlight5980

Copy link
Copy Markdown
Collaborator Author

[P2] Preserve active membership when transferring ownership

The transaction validates the target member with status: active at pro/admin/src/service/support/user/team/controller/changeOwner.ts:46-49, but the role update at pro/admin/src/service/support/user/team/controller/changeOwner.ts:83-89 matches only { userId, teamId }. Since pro/admin/src/pages/api/support/user/team/member/updateInvite.ts:22-32 can concurrently change the same member to leave or forbidden without taking the team lock, this request can still set a non-active member as the team owner.

Please serialize member-status changes with the same team lock, and/or include status: active in this update predicate and fail the transaction when no row is matched. Add a regression test covering the status change between validation and the owner update.

resolved

@shortlight5980

Copy link
Copy Markdown
Collaborator Author

P1: The user lock is released before the outer Mongo transaction commits. In packages/service/support/user/team/controller.ts:153-157, createUserLoginTeam runs the fallback check and team creation inside withUserLock, but this function is called from the handler of passwordVerificationService.consumeInTransaction. That outer transaction commits only after the handler returns. Therefore, a second concurrent login with a different valid pre-login code can acquire the lock while the first team inserts are still uncommitted; its transaction cannot see the first team and can create another owner team for the same user. Please keep the lock around the whole transaction, or add a database-level idempotency/serialization guarantee, and add a concurrent-login regression test.

resolved

@shortlight5980

Copy link
Copy Markdown
Collaborator Author

P1: Sync mode ownership transfer can be bypassed through the API. In pro/admin/src/service/support/user/team/controller/changeOwner.ts:62-64, the backend rejects non-WeCom teams only when teamMode is single. The frontend hides the transfer action whenever isSyncMode is true (projects/app/src/pageComponents/account/team/MemberTable.tsx:236-238), but a current team owner can call the endpoint directly in sync mode and transfer ownership of a non-WeCom team. Please enforce the same mode restriction in the backend rather than relying on the UI, and add an API/service regression test for sync mode.

resolved

@FinleyGe

FinleyGe commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

[P1] Race condition between owner transfer and member removal (confidence: 9/10)

teamChangeOwner serializes the ownership transfer with withTeamLock(teamId, ...) at pro/admin/src/service/support/user/team/controller/changeOwner.ts:32, but removeUserFromTeam does not acquire the same team lock. It reads removeTmb and ownerTmb at pro/admin/src/service/support/user/controller.ts:768-785, then unconditionally sets removeTmb.status to leave or forbidden at :864-870.

A concrete interleaving is: removal of member B reads B as a non-owner while A is still the owner; the A -> B transfer then completes; the removal continues and saves B as leave. The team can then point to B as ownerId while B is no longer an active member, and the removal path may also transfer B’s resources to A.

Please make removeUserFromTeam share the same team-level lock and preserve the existing session/transaction behavior, or otherwise make the ownership and member-status transition atomic.

Comment thread packages/global/common/error/code/team.ts Outdated
@shortlight5980

Copy link
Copy Markdown
Collaborator Author

[P1] Race condition between owner transfer and member removal (confidence: 9/10)

teamChangeOwner serializes the ownership transfer with withTeamLock(teamId, ...) at pro/admin/src/service/support/user/team/controller/changeOwner.ts:32, but removeUserFromTeam does not acquire the same team lock. It reads removeTmb and ownerTmb at pro/admin/src/service/support/user/controller.ts:768-785, then unconditionally sets removeTmb.status to leave or forbidden at :864-870.

A concrete interleaving is: removal of member B reads B as a non-owner while A is still the owner; the A -> B transfer then completes; the removal continues and saves B as leave. The team can then point to B as ownerId while B is no longer an active member, and the removal path may also transfer B’s resources to A.

Please make removeUserFromTeam share the same team-level lock and preserve the existing session/transaction behavior, or otherwise make the ownership and member-status transition atomic.

resolved

@FinleyGe FinleyGe left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avaliable for testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants