Skip to content

Commit 46417dd

Browse files
authored
feat(invitations): added FF to disable invitations, added to permission groups, added workspace members admin endpoints (#2783)
* feat(invitations): added FF to disable invitations, added to permission groups, added workspace members admin endpoints * fix failing tests
1 parent b6cbee2 commit 46417dd

File tree

25 files changed

+716
-24
lines changed

25 files changed

+716
-24
lines changed

apps/docs/content/docs/de/enterprise/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Für selbst gehostete Bereitstellungen können Enterprise-Funktionen über Umgeb
7070
|----------|-------------|
7171
| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | Single Sign-On mit SAML/OIDC |
7272
| `CREDENTIAL_SETS_ENABLED`, `NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | Polling-Gruppen für E-Mail-Trigger |
73+
| `DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS` | Workspace-/Organisations-Einladungen global deaktivieren |
7374

7475
<Callout type="warn">
7576
BYOK ist nur im gehosteten Sim Studio verfügbar. Selbst gehostete Deployments konfigurieren AI-Provider-Schlüssel direkt über Umgebungsvariablen.

apps/docs/content/docs/en/enterprise/index.mdx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Define permission groups to control what features and integrations team members
1717

1818
- **Allowed Model Providers** - Restrict which AI providers users can access (OpenAI, Anthropic, Google, etc.)
1919
- **Allowed Blocks** - Control which workflow blocks are available
20-
- **Platform Settings** - Hide Knowledge Base, disable MCP tools, or disable custom tools
20+
- **Platform Settings** - Hide Knowledge Base, disable MCP tools, disable custom tools, or disable invitations
2121

2222
### Setup
2323

@@ -68,6 +68,7 @@ For self-hosted deployments, enterprise features can be enabled via environment
6868
| `ACCESS_CONTROL_ENABLED`, `NEXT_PUBLIC_ACCESS_CONTROL_ENABLED` | Permission groups for access restrictions |
6969
| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | Single Sign-On with SAML/OIDC |
7070
| `CREDENTIAL_SETS_ENABLED`, `NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | Polling Groups for email triggers |
71+
| `DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS` | Globally disable workspace/organization invitations |
7172

7273
### Organization Management
7374

@@ -87,6 +88,23 @@ curl -X POST https://your-instance/api/v1/admin/organizations/{orgId}/members \
8788
-d '{"userId": "user-id-here", "role": "admin"}'
8889
```
8990

91+
### Workspace Members
92+
93+
When invitations are disabled, use the Admin API to manage workspace memberships directly:
94+
95+
```bash
96+
# Add a user to a workspace
97+
curl -X POST https://your-instance/api/v1/admin/workspaces/{workspaceId}/members \
98+
-H "x-admin-key: YOUR_ADMIN_API_KEY" \
99+
-H "Content-Type: application/json" \
100+
-d '{"userId": "user-id-here", "permissions": "write"}'
101+
102+
# Remove a user from a workspace
103+
curl -X DELETE "https://your-instance/api/v1/admin/workspaces/{workspaceId}/members?userId=user-id-here" \
104+
-H "x-admin-key: YOUR_ADMIN_API_KEY"
105+
```
106+
90107
### Notes
91108

92109
- Enabling `ACCESS_CONTROL_ENABLED` automatically enables organizations, as access control requires organization membership.
110+
- When `DISABLE_INVITATIONS` is set, users cannot send invitations. Use the Admin API to manage workspace and organization memberships instead.

apps/docs/content/docs/es/enterprise/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Para implementaciones self-hosted, las funciones enterprise se pueden activar me
7070
|----------|-------------|
7171
| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | Inicio de sesión único con SAML/OIDC |
7272
| `CREDENTIAL_SETS_ENABLED`, `NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | Grupos de sondeo para activadores de correo electrónico |
73+
| `DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS` | Desactivar globalmente invitaciones a espacios de trabajo/organizaciones |
7374

7475
<Callout type="warn">
7576
BYOK solo está disponible en Sim Studio alojado. Las implementaciones autoalojadas configuran las claves de proveedor de IA directamente a través de variables de entorno.

apps/docs/content/docs/fr/enterprise/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Pour les déploiements auto-hébergés, les fonctionnalités entreprise peuvent
7070
|----------|-------------|
7171
| `SSO_ENABLED`, `NEXT_PUBLIC_SSO_ENABLED` | Authentification unique avec SAML/OIDC |
7272
| `CREDENTIAL_SETS_ENABLED`, `NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | Groupes de sondage pour les déclencheurs d'e-mail |
73+
| `DISABLE_INVITATIONS`, `NEXT_PUBLIC_DISABLE_INVITATIONS` | Désactiver globalement les invitations aux espaces de travail/organisations |
7374

7475
<Callout type="warn">
7576
BYOK est uniquement disponible sur Sim Studio hébergé. Les déploiements auto-hébergés configurent les clés de fournisseur d'IA directement via les variables d'environnement.

apps/docs/content/docs/ja/enterprise/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Sim Studioのホストキーの代わりに、AIモデルプロバイダー用
6969
|----------|-------------|
7070
| `SSO_ENABLED``NEXT_PUBLIC_SSO_ENABLED` | SAML/OIDCによるシングルサインオン |
7171
| `CREDENTIAL_SETS_ENABLED``NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | メールトリガー用のポーリンググループ |
72+
| `DISABLE_INVITATIONS``NEXT_PUBLIC_DISABLE_INVITATIONS` | ワークスペース/組織への招待をグローバルに無効化 |
7273

7374
<Callout type="warn">
7475
BYOKはホスト型Sim Studioでのみ利用可能です。セルフホスト型デプロイメントでは、環境変数を介してAIプロバイダーキーを直接設定します。

apps/docs/content/docs/zh/enterprise/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Sim Studio 企业版为需要更高安全性、合规性和管理能力的组织
6969
|----------|-------------|
7070
| `SSO_ENABLED``NEXT_PUBLIC_SSO_ENABLED` | 使用 SAML/OIDC 的单点登录 |
7171
| `CREDENTIAL_SETS_ENABLED``NEXT_PUBLIC_CREDENTIAL_SETS_ENABLED` | 用于邮件触发器的轮询组 |
72+
| `DISABLE_INVITATIONS``NEXT_PUBLIC_DISABLE_INVITATIONS` | 全局禁用工作区/组织邀请 |
7273

7374
<Callout type="warn">
7475
BYOK 仅适用于托管版 Sim Studio。自托管部署需通过环境变量直接配置 AI 提供商密钥。

apps/sim/app/api/organizations/[id]/invitations/route.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ import { getBaseUrl } from '@/lib/core/utils/urls'
2626
import { sendEmail } from '@/lib/messaging/email/mailer'
2727
import { quickValidateEmail } from '@/lib/messaging/email/validation'
2828
import { hasWorkspaceAdminAccess } from '@/lib/workspaces/permissions/utils'
29+
import {
30+
InvitationsNotAllowedError,
31+
validateInvitationsAllowed,
32+
} from '@/executor/utils/permission-check'
2933

3034
const logger = createLogger('OrganizationInvitations')
3135

@@ -116,6 +120,8 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
116120
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
117121
}
118122

123+
await validateInvitationsAllowed(session.user.id)
124+
119125
const { id: organizationId } = await params
120126
const url = new URL(request.url)
121127
const validateOnly = url.searchParams.get('validate') === 'true'
@@ -427,6 +433,10 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
427433
},
428434
})
429435
} catch (error) {
436+
if (error instanceof InvitationsNotAllowedError) {
437+
return NextResponse.json({ error: error.message }, { status: 403 })
438+
}
439+
430440
logger.error('Failed to create organization invitations', {
431441
organizationId: (await params).id,
432442
error,
@@ -486,10 +496,7 @@ export async function DELETE(
486496
and(
487497
eq(invitation.id, invitationId),
488498
eq(invitation.organizationId, organizationId),
489-
or(
490-
eq(invitation.status, 'pending'),
491-
eq(invitation.status, 'rejected') // Allow cancelling rejected invitations too
492-
)
499+
or(eq(invitation.status, 'pending'), eq(invitation.status, 'rejected'))
493500
)
494501
)
495502
.returning()

apps/sim/app/api/v1/admin/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
* Workspaces:
1818
* GET /api/v1/admin/workspaces - List all workspaces
1919
* GET /api/v1/admin/workspaces/:id - Get workspace details
20+
* GET /api/v1/admin/workspaces/:id/members - List workspace members
21+
* POST /api/v1/admin/workspaces/:id/members - Add/update workspace member
22+
* DELETE /api/v1/admin/workspaces/:id/members?userId=X - Remove workspace member
23+
* GET /api/v1/admin/workspaces/:id/members/:mid - Get workspace member details
24+
* PATCH /api/v1/admin/workspaces/:id/members/:mid - Update workspace member permissions
25+
* DELETE /api/v1/admin/workspaces/:id/members/:mid - Remove workspace member by ID
2026
* GET /api/v1/admin/workspaces/:id/workflows - List workspace workflows
2127
* DELETE /api/v1/admin/workspaces/:id/workflows - Delete all workspace workflows
2228
* GET /api/v1/admin/workspaces/:id/folders - List workspace folders
@@ -95,6 +101,7 @@ export type {
95101
AdminWorkflowDetail,
96102
AdminWorkspace,
97103
AdminWorkspaceDetail,
104+
AdminWorkspaceMember,
98105
DbMember,
99106
DbOrganization,
100107
DbSubscription,

apps/sim/app/api/v1/admin/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,22 @@ export interface AdminMemberDetail extends AdminMember {
518518
billingBlocked: boolean
519519
}
520520

521+
// =============================================================================
522+
// Workspace Member Types
523+
// =============================================================================
524+
525+
export interface AdminWorkspaceMember {
526+
id: string
527+
workspaceId: string
528+
userId: string
529+
permissions: 'admin' | 'write' | 'read'
530+
createdAt: string
531+
updatedAt: string
532+
userName: string
533+
userEmail: string
534+
userImage: string | null
535+
}
536+
521537
// =============================================================================
522538
// User Billing Types
523539
// =============================================================================

0 commit comments

Comments
 (0)