diff --git a/.env.example b/.env.example index d31e89dd21..bd33d9cdb0 100644 --- a/.env.example +++ b/.env.example @@ -34,11 +34,11 @@ SMTP_PASSWORD= SMTP_DOMAIN= SMTP_PORT= -# DISABLE USER SIGNUPS (true or false). only applicable if MULTI_ORGANIZATION=true +# DISABLE USER SIGNUPS (true or false). only applicable if Multi-Workspace feature is enabled DISABLE_SIGNUPS= -# Enables all multi organization features -MULTI_ORGANIZATION= +# Disable Multi-Workspace features (true or false) +DISABLE_MULTI_WORKSPACE= # OBSERVABILITY APM_VENDOR= diff --git a/app.json b/app.json index 17d25a93c9..703237fcfb 100644 --- a/app.json +++ b/app.json @@ -34,11 +34,11 @@ "value": "--max-old-space-size=4096" }, "DISABLE_SIGNUPS": { - "description": "Disable sign up in login page only applicable if MULTI_ORGANIZATION=true", + "description": "Disable sign up in login page only applicable if Multi-Workspace feature is turned on", "value": "false" }, - "MULTI_ORGANIZATION": { - "description": "Enables multi organization feature", + "DISABLE_MULTI_WORKSPACE": { + "description": "Disables Multi-Workspace feature", "value": "false" } }, diff --git a/docs/docs/password-login/password-login.md b/docs/docs/password-login/password-login.md index 620ed24ae7..9297925435 100644 --- a/docs/docs/password-login/password-login.md +++ b/docs/docs/password-login/password-login.md @@ -5,9 +5,9 @@ sidebar_label: Password Login # Password Login -Password login is enabled by default for all organizations. User with admin privilege can enable/disable it. +Password login is enabled by default for all workspaces. User with admin privilege can enable/disable it. -Select `Manage SSO` from organization options +Select `Manage SSO` from workspace options
diff --git a/docs/docs/setup/env-vars.md b/docs/docs/setup/env-vars.md index 75fc391d5f..5f8e58df4d 100644 --- a/docs/docs/setup/env-vars.md +++ b/docs/docs/setup/env-vars.md @@ -73,14 +73,14 @@ You can specify a different server for backend if it is hosted on another server | -------- | ---------------------- | | SERVER_HOST | Configure a hostname for the server as a proxy pass. If no value is set, it defaults to `server`. | -#### Enable multiple organizations ( optional ) +#### Disable Multi-Workspace ( optional ) -If you want to enable multiple environments, set the environment variable `MULTI_ORGANIZATION` to `true`. +If you want to disable Multi-Workspace feature, set the environment variable `DISABLE_MULTI_WORKSPACE` to `true`. #### Disabling signups ( optional ) -Sign up is enabled only for multiple organization environment. If you want to restrict the signups and allow new users only by invitations, set the environment variable `DISABLE_SIGNUPS` to `true`. +Sign up is enabled only if Multi-Workspace is enabled. If you want to restrict the signups and allow new users only by invitations, set the environment variable `DISABLE_SIGNUPS` to `true`. :::tip You will still be able to see the signup page but won't be able to successfully submit the form. @@ -93,7 +93,7 @@ You can set `SERVE_CLIENT` to `true` and the server will attempt to serve the cl #### SMTP configuration ( optional ) -ToolJet uses SMTP services to send emails ( Eg: invitation email when you add new users to your organization ). +ToolJet uses SMTP services to send emails ( Eg: invitation email when you add new users to your workspace ). | variable | description | | ------------------ | ----------------------------------------- | diff --git a/docs/docs/sso/general-settings.md b/docs/docs/sso/general-settings.md index 87c8bc8d87..82436bbad2 100644 --- a/docs/docs/sso/general-settings.md +++ b/docs/docs/sso/general-settings.md @@ -5,7 +5,7 @@ sidebar_label: General Settings # Single Sign-On General Settings -Select `Manage SSO` from organization options +Select `Manage SSO` from workspace options
diff --git a/docs/docs/sso/github.md b/docs/docs/sso/github.md index 1d5aa22e2f..a7faf8bb4c 100644 --- a/docs/docs/sso/github.md +++ b/docs/docs/sso/github.md @@ -5,7 +5,7 @@ title: GitHub # GitHub Single Sign-on -Select `Manage SSO` from organization options +Select `Manage SSO` from workspace options
@@ -55,4 +55,4 @@ Go to [GitHub Developer settings](https://github.com/settings/developers) and na Lastly, enter `Client Id` and `Client Secret` in Git manage SSO page and save. -The GitHub sign-in button will now be available in your ToolJet login screen if you have not enabled multiple organization. +The GitHub sign-in button will now be available in your ToolJet login screen if you have not enabled Multi-Workspace. diff --git a/docs/docs/sso/google.md b/docs/docs/sso/google.md index b7a1988265..43c25cbe3d 100644 --- a/docs/docs/sso/google.md +++ b/docs/docs/sso/google.md @@ -5,7 +5,7 @@ title: Google # Google Single Sign-on -Select `Manage SSO` from organization options +Select `Manage SSO` from workspace options
@@ -45,7 +45,7 @@ Go to [Google cloud console](https://console.cloud.google.com/) and create a pro
-- You'll be asked to select user type in consent screen. To allow only users within your organization, select 'Internal', otherwise, +- You'll be asked to select user type in consent screen. To allow only users within your workspace, select 'Internal', otherwise, select 'External'.
@@ -82,4 +82,4 @@ Set the `Redirect URL` generated at manage SSO `Google` page under Authorised re Lastly, set the `client id` in google manage SSO page. This value will be available from your [Google cloud console credentials page](https://console.cloud.google.com/apis/credentials) -The Google sign-in button will now be available in your ToolJet login screen, if you are not enabled multiple organization. +The Google sign-in button will now be available in your ToolJet login screen, if you are not enabled Multi-Workspace. diff --git a/docs/docs/tutorial/adding-a-datasource.md b/docs/docs/tutorial/adding-a-datasource.md index 2d46d1e914..75a1d2be88 100644 --- a/docs/docs/tutorial/adding-a-datasource.md +++ b/docs/docs/tutorial/adding-a-datasource.md @@ -6,7 +6,7 @@ title: Adding a data source # Adding a data source :::tip -The data sources are created on app level and not on organization level. +The data sources are created on app level and not on workspace level. ::: **Datasource manager** is on the left-sidebar of the app builder. To add a new data source, click on the `Add datasource` button. diff --git a/docs/docs/tutorial/manage-users-groups.md b/docs/docs/tutorial/manage-users-groups.md index 9c3bf778ee..f1d62f21e1 100644 --- a/docs/docs/tutorial/manage-users-groups.md +++ b/docs/docs/tutorial/manage-users-groups.md @@ -7,7 +7,7 @@ title: Managing Users and Groups ## Managing Users -Admin of an organization can add users to the organization. To manage the users in your organization, just go to the **Account menu** on top right corner and click on the **Manage Users**. +Admin of a workspace can add users to the workspace. To manage the users in your workspace, just go to the **Workspace menu** on top right corner and click on the **Manage Users**.
@@ -17,7 +17,7 @@ Admin of an organization can add users to the organization. To manage the users ### Inviting users -Admins can invite anyone to a ToolJet organization using the email address. To invite a user: +Admins can invite anyone to a workspace using the email address. To invite a user: - On the **Manage Users** page click on the `Invite new user` button. @@ -35,7 +35,7 @@ Admins can invite anyone to a ToolJet organization using the email address. To i
-- An email including the **Invite Link** to join your organization will be send to the created user. The status will turn from **invited** to **active** after the user successfully joins your organization using the invite link. +- An email including the **Invite Link** to join your workspace will be send to the created user. The status will turn from **invited** to **active** after the user successfully joins your workspace using the invite link. :::tip @@ -51,7 +51,7 @@ You can also copy the invitation url by clicking on the copy icon next to `invit ### Disabling a user's access -You can disable any active user's access to your organization by clicking on the **Archive** and then the status of the user will change from **active** to **archived**. +You can disable any active user's access to your workspace by clicking on the **Archive** and then the status of the user will change from **active** to **archived**.
@@ -71,7 +71,7 @@ Similar to archiving a user's access, you can enable it again by clicking on **U ## Managing Groups -On ToolJet, Admins can create groups for users added in an organization and grant them access to particular app(s) with specific permissions. To manage groups, just go to the **Account menu** on top right corner and click on the **Manage Groups**. +On ToolJet, Admins can create groups for users added in a workspace and grant them access to particular app(s) with specific permissions. To manage groups, just go to the **Account menu** on top right corner and click on the **Manage Groups**.
@@ -115,13 +115,13 @@ Admins can set granular permission like creating/deleting apps or creating folde :::tip -All the activities performed by any Admin or any user in a ToolJet organization is logged in `Audit logs` - including any activity related with managing users and groups. +All the activities performed by any Admin or any user in a workspace is logged in `Audit logs` - including any activity related with managing users and groups. ::: ### Predefined Groups -By default, every organization will have two User Groups: +By default, every workspace will have two User Groups: **1. All Users** @@ -129,7 +129,7 @@ This group contains all the users and admins. | Apps | Users | Permissions | | ----------- | ----------- | ----------- | -| You can add or remove apps. | Modification is disabled. This group will have all the users and admins added in an organization. | You can edit permissions for all the users globally. | +| You can add or remove apps. | Modification is disabled. This group will have all the users and admins added in a workspace. | You can edit permissions for all the users globally. |
@@ -143,7 +143,7 @@ This group contains admins by default. Admins can add more admins or remove the | Apps | Users | Permissions | | ----------- | ----------- | ----------- | -| Modification is disabled. By default, this group has `Edit` permission for all the apps in an organization | Admins can add or remove users in this group. | Modification is disabled. By default, all the admins can create and delete apps or create folders. | +| Modification is disabled. By default, this group has `Edit` permission for all the apps in a workspace | Admins can add or remove users in this group. | Modification is disabled. By default, all the admins can create and delete apps or create folders. |
diff --git a/frontend/src/ConfirmationPage/ConfirmationPage.jsx b/frontend/src/ConfirmationPage/ConfirmationPage.jsx index f28bb089ef..7ba00652cd 100644 --- a/frontend/src/ConfirmationPage/ConfirmationPage.jsx +++ b/frontend/src/ConfirmationPage/ConfirmationPage.jsx @@ -126,7 +126,7 @@ class ConfirmationPage extends React.Component {
- +
{ @@ -49,7 +49,7 @@ class OrganizationInvitationPage extends React.Component { }) .then(() => { this.setState({ isLoading: false }); - toast.success(`Added to the organization${isSetPassword ? ' and password has been set ' : ' '}successfully.`, { + toast.success(`Added to the workspace${isSetPassword ? ' and password has been set ' : ' '}successfully.`, { position: 'top-center', }); this.props.history.push('/login'); diff --git a/frontend/src/Editor/ManageAppUsers.jsx b/frontend/src/Editor/ManageAppUsers.jsx index afe9055894..0296b97bc1 100644 --- a/frontend/src/Editor/ManageAppUsers.jsx +++ b/frontend/src/Editor/ManageAppUsers.jsx @@ -306,7 +306,7 @@ class ManageAppUsers extends React.Component { - Manage Organization Users + Manage Users diff --git a/frontend/src/LoginPage/LoginPage.jsx b/frontend/src/LoginPage/LoginPage.jsx index f422826887..89d581085d 100644 --- a/frontend/src/LoginPage/LoginPage.jsx +++ b/frontend/src/LoginPage/LoginPage.jsx @@ -16,7 +16,7 @@ class LoginPage extends React.Component { isGettingConfigs: true, configs: undefined, }; - this.single_organization = window.public_config?.MULTI_ORGANIZATION !== 'true'; + this.single_organization = window.public_config?.DISABLE_MULTI_WORKSPACE === 'true'; } componentDidMount() { @@ -132,7 +132,7 @@ class LoginPage extends React.Component { this.showLoading() ) : (
- {!configs &&
No login methods enabled for this organization
} + {!configs &&
No login methods enabled for this workspace
} {configs?.form?.enabled && (

diff --git a/frontend/src/ManageSSO/Google.jsx b/frontend/src/ManageSSO/Google.jsx index 5c49075383..025b3b3725 100644 --- a/frontend/src/ManageSSO/Google.jsx +++ b/frontend/src/ManageSSO/Google.jsx @@ -77,7 +77,7 @@ export function Google({ settings, updateData }) { setClientId(e.target.value)} /> diff --git a/frontend/src/_components/Organization.jsx b/frontend/src/_components/Organization.jsx index 9b65d3f4a9..8f2d1aa138 100644 --- a/frontend/src/_components/Organization.jsx +++ b/frontend/src/_components/Organization.jsx @@ -6,7 +6,7 @@ import { toast } from 'react-hot-toast'; import { SearchBox } from './SearchBox'; export const Organization = function Organization() { - const isSingleOrganization = window.public_config?.MULTI_ORGANIZATION !== 'true'; + const isSingleOrganization = window.public_config?.DISABLE_MULTI_WORKSPACE === 'true'; const { admin, organization_id } = authenticationService.currentUserValue; const [organization, setOrganization] = useState(authenticationService.currentUserValue?.organization); const [showCreateOrg, setShowCreateOrg] = useState(false); @@ -21,11 +21,13 @@ export const Organization = function Organization() { const getAvatar = (organization) => { if (!organization) return; - const orgName = organization.split(' '); + const orgName = organization.split(' ').filter((e) => e && !!e.trim()); if (orgName.length > 1) { return `${orgName[0]?.[0]}${orgName[1]?.[0]}`; - } else { + } else if (organization.length >= 2) { return `${organization[0]}${organization[1]}`; + } else { + return `${organization[0]}${organization[0]}`; } }; @@ -58,7 +60,7 @@ export const Organization = function Organization() { const createOrganization = () => { if (!(newOrgName && newOrgName.trim())) { - toast.error("organization name can't be empty.", { + toast.error('Workspace name can not be empty.', { position: 'top-center', }); return; @@ -66,21 +68,22 @@ export const Organization = function Organization() { setIsCreating(true); organizationService.createOrganization(newOrgName).then( (data) => { + setIsCreating(false); authenticationService.updateCurrentUserDetails(data); window.location.href = '/'; }, () => { - toast.error('Error while creating organization', { + setIsCreating(false); + toast.error('Error while creating workspace', { position: 'top-center', }); } ); - setIsCreating(false); }; const editOrganization = () => { if (!(newOrgName && newOrgName.trim())) { - toast.error("organization name can't be empty.", { + toast.error('Workspace name can not be empty.', { position: 'top-center', }); return; @@ -89,13 +92,13 @@ export const Organization = function Organization() { organizationService.editOrganization({ name: newOrgName }).then( () => { authenticationService.updateCurrentUserDetails({ organization: newOrgName }); - toast.success('Organization updated', { + toast.success('Workspace updated', { position: 'top-center', }); setOrganization(newOrgName); }, () => { - toast.error('Error while editing organization', { + toast.error('Error while editing workspace', { position: 'top-center', }); } @@ -258,7 +261,7 @@ export const Organization = function Organization() {

{!isSingleOrganization && (
-
Add Organizations
+
Add workspace
)} {admin && ( @@ -281,8 +284,12 @@ export const Organization = function Organization() { return (
-
setIsListOrganizations(false)}> - +
+ setIsListOrganizations(false)} + >
{organization}
{(!isSingleOrganization || admin) && ( @@ -291,14 +298,14 @@ export const Organization = function Organization() {
)}
- setShowCreateOrg(false)} title="Create organization"> + setShowCreateOrg(false)} title="Create workspace">
setNewOrgName(e.target.value)} className="form-control" - placeholder="organization name" + placeholder="workspace name" disabled={isCreating} maxLength={25} /> @@ -314,19 +321,19 @@ export const Organization = function Organization() { className={`btn btn-primary ${isCreating ? 'btn-loading' : ''}`} onClick={createOrganization} > - Create organization + Create workspace
- setShowEditOrg(false)} title="Edit organization"> + setShowEditOrg(false)} title="Edit workspace">
setNewOrgName(e.target.value)} className="form-control" - placeholder="organization name" + placeholder="workspace name" disabled={isCreating} value={newOrgName} maxLength={25} diff --git a/server/ee/services/oauth/oauth.service.ts b/server/ee/services/oauth/oauth.service.ts index 969da0625b..e39d262629 100644 --- a/server/ee/services/oauth/oauth.service.ts +++ b/server/ee/services/oauth/oauth.service.ts @@ -63,12 +63,12 @@ export class OauthService { async #findAndActivateUser(email: string, organizationId: string): Promise { const user = await this.usersService.findByEmail(email, organizationId); if (!user) { - throw new UnauthorizedException('User not exist in the organization'); + throw new UnauthorizedException('User not exist in the workspace'); } const organizationUser: OrganizationUser = user.organizationUsers?.[0]; if (!organizationUser) { - throw new UnauthorizedException('User not exist in the organization'); + throw new UnauthorizedException('User not exist in the workspace'); } if (organizationUser.status != 'active') await this.organizationUsersService.activate(organizationUser); return user; diff --git a/server/migrations/1650485473528-PopulateSSOConfigs.ts b/server/migrations/1650485473528-PopulateSSOConfigs.ts index d22725d66d..fa35d95b6c 100644 --- a/server/migrations/1650485473528-PopulateSSOConfigs.ts +++ b/server/migrations/1650485473528-PopulateSSOConfigs.ts @@ -9,7 +9,7 @@ export class PopulateSSOConfigs1650485473528 implements MigrationInterface { const encryptionService = new EncryptionService(); const OrganizationRepository = entityManager.getRepository(Organization); - const isSingleOrganization = process.env.MULTI_ORGANIZATION !== 'true'; + const isSingleOrganization = process.env.DISABLE_MULTI_WORKSPACE === 'true'; const enableSignUp = process.env.SSO_DISABLE_SIGNUP !== 'true'; const domain = process.env.SSO_RESTRICTED_DOMAIN; diff --git a/server/src/controllers/organizations.controller.ts b/server/src/controllers/organizations.controller.ts index ef560507ae..2996810297 100644 --- a/server/src/controllers/organizations.controller.ts +++ b/server/src/controllers/organizations.controller.ts @@ -49,7 +49,7 @@ export class OrganizationsController { @Get(['/:organizationId/public-configs', '/public-configs']) async getOrganizationDetails(@Param('organizationId') organizationId: string) { - if (!organizationId && this.configService.get('MULTI_ORGANIZATION') !== 'true') { + if (!organizationId && this.configService.get('DISABLE_MULTI_WORKSPACE') === 'true') { // Request from single organization login page - find one from organization and setting organizationId = (await this.organizationsService.getSingleOrganization()).id; } diff --git a/server/src/modules/auth/multi-organization.guard.ts b/server/src/modules/auth/multi-organization.guard.ts index ef84dbefd4..f2797b7e25 100644 --- a/server/src/modules/auth/multi-organization.guard.ts +++ b/server/src/modules/auth/multi-organization.guard.ts @@ -7,6 +7,6 @@ export class MultiOrganizationGuard implements CanActivate { constructor(private configService: ConfigService) {} canActivate(context: ExecutionContext): boolean | Promise | Observable { - return this.configService.get('MULTI_ORGANIZATION') === 'true'; + return this.configService.get('DISABLE_MULTI_WORKSPACE') !== 'true'; } } diff --git a/server/src/services/app_config.service.ts b/server/src/services/app_config.service.ts index 066c7b43e2..52fa315d4f 100644 --- a/server/src/services/app_config.service.ts +++ b/server/src/services/app_config.service.ts @@ -23,7 +23,7 @@ export class AppConfigService { 'SENTRY_DNS', 'SENTRY_DEBUG', 'DISABLE_SIGNUPS', - 'MULTI_ORGANIZATION', + 'DISABLE_MULTI_WORKSPACE', ]; } diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index 61653c45b3..92a7a6ed22 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -51,7 +51,7 @@ export class AuthService { if (!organizationId) { // Global login // Determine the organization to be loaded - if (this.configService.get('MULTI_ORGANIZATION') !== 'true') { + if (this.configService.get('DISABLE_MULTI_WORKSPACE') === 'true') { // Single organization organization = await this.organizationsService.getSingleOrganization(); if (!organization?.ssoConfigs?.find((oc) => oc.sso == 'form' && oc.enabled)) { @@ -72,7 +72,7 @@ export class AuthService { organization = organizationList[0]; } else { // no form login enabled organization available for user - creating new one - organization = await this.organizationsService.create('Untitled organization', user); + organization = await this.organizationsService.create('Untitled workspace', user); } } user.organizationId = organization.id; @@ -122,7 +122,7 @@ export class AuthService { if (!(isNewOrganization || user.isPasswordLogin)) { throw new UnauthorizedException(); } - if (this.configService.get('MULTI_ORGANIZATION') !== 'true') { + if (this.configService.get('DISABLE_MULTI_WORKSPACE') === 'true') { throw new UnauthorizedException(); } const newUser = await this.usersService.findByEmail(user.email, newOrganizationId); @@ -174,7 +174,7 @@ export class AuthService { let organization: Organization; // Check if the configs allows user signups - if (this.configService.get('MULTI_ORGANIZATION') !== 'true') { + if (this.configService.get('DISABLE_MULTI_WORKSPACE') === 'true') { // Single organization checking if organization exist organization = await this.organizationsService.getSingleOrganization(); @@ -188,7 +188,7 @@ export class AuthService { } } // Create default organization - organization = await this.organizationsService.create('Untitled organization'); + organization = await this.organizationsService.create('Untitled workspace'); const user = await this.usersService.create({ email }, organization.id, ['all_users', 'admin'], existingUser, true); await this.organizationUsersService.create(user, organization, true); await this.emailService.sendWelcomeEmail(user.email, user.firstName, user.invitationToken); diff --git a/server/src/services/email.service.ts b/server/src/services/email.service.ts index 5a0a6dfd05..e6f90229d0 100644 --- a/server/src/services/email.service.ts +++ b/server/src/services/email.service.ts @@ -100,7 +100,7 @@ export class EmailService {

Hi ${name || ''},


- ${sender} has invited you to use ToolJet organisation ${organisationName}. Use the link below to set up your account and get started. + ${sender} has invited you to use ToolJet workspace ${organisationName}. Use the link below to set up your account and get started.
${inviteUrl} diff --git a/server/src/services/seeds.service.ts b/server/src/services/seeds.service.ts index fe8599e721..e4938c596f 100644 --- a/server/src/services/seeds.service.ts +++ b/server/src/services/seeds.service.ts @@ -30,7 +30,7 @@ export class SeedsService { sso: 'form', }, ], - name: 'My organization', + name: 'My workspace', }); await manager.save(organization); diff --git a/server/test/controllers/app.e2e-spec.ts b/server/test/controllers/app.e2e-spec.ts index 74f9fa4f75..a712fcb4eb 100644 --- a/server/test/controllers/app.e2e-spec.ts +++ b/server/test/controllers/app.e2e-spec.ts @@ -38,6 +38,18 @@ describe('Authentication', () => { }); describe('Single organization', () => { + beforeEach(async () => { + jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { + switch (key) { + case 'DISABLE_SIGNUPS': + return 'false'; + case 'DISABLE_MULTI_WORKSPACE': + return 'true'; + default: + return process.env[key]; + } + }); + }); it('should create new users and organization', async () => { const response = await request(app.getHttpServer()).post('/api/signup').send({ email: 'test@tooljet.io' }); expect(response.statusCode).toBe(201); @@ -52,7 +64,7 @@ describe('Authentication', () => { }); expect(user.defaultOrganizationId).toBe(user?.organizationUsers?.[0]?.organizationId); - expect(organization.name).toBe('Untitled organization'); + expect(organization.name).toBe('Untitled workspace'); const groupPermissions = await user.groupPermissions; const groupNames = groupPermissions.map((x) => x.group); @@ -142,8 +154,6 @@ describe('Authentication', () => { switch (key) { case 'DISABLE_SIGNUPS': return 'false'; - case 'MULTI_ORGANIZATION': - return 'true'; default: return process.env[key]; } @@ -155,8 +165,6 @@ describe('Authentication', () => { switch (key) { case 'DISABLE_SIGNUPS': return 'true'; - case 'MULTI_ORGANIZATION': - return 'true'; default: return process.env[key]; } @@ -182,7 +190,7 @@ describe('Authentication', () => { }); expect(user.defaultOrganizationId).toBe(user?.organizationUsers?.[0]?.organizationId); - expect(organization?.name).toBe('Untitled organization'); + expect(organization?.name).toBe('Untitled workspace'); const groupPermissions = await user.groupPermissions; const groupNames = groupPermissions.map((x) => x.group); @@ -255,7 +263,7 @@ describe('Authentication', () => { .send({ email: 'admin@tooljet.io', password: 'password' }); expect(response.statusCode).toBe(201); expect(response.body.organization_id).not.toBe(current_organization.id); - expect(response.body.organization).toBe('Untitled organization'); + expect(response.body.organization).toBe('Untitled workspace'); }); it('should be able to switch between organizations with admin privilage', async () => { const { organization: invited_organization } = await createUser( diff --git a/server/test/controllers/oauth.e2e-spec.ts b/server/test/controllers/oauth.e2e-spec.ts index 1d043ee4d0..5ea15f6438 100644 --- a/server/test/controllers/oauth.e2e-spec.ts +++ b/server/test/controllers/oauth.e2e-spec.ts @@ -19,13 +19,6 @@ describe('oauth controller', () => { beforeEach(async () => { await clearDB(); - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - if (key === 'MULTI_ORGANIZATION') { - return 'false'; - } else { - return process.env[key]; - } - }); }); beforeAll(async () => { @@ -57,917 +50,1844 @@ describe('oauth controller', () => { current_organization = organization; }); - describe('sign in via Google OAuth', () => { - let sso_configs; - const token = 'some-Token'; - beforeEach(() => { - sso_configs = current_organization.ssoConfigs.find((conf) => conf.sso === 'google'); - }); - it('should return 401 if google sign in is disabled', async () => { - await ssoConfigsRepository.update(sso_configs.id, { enabled: false }); - await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }) - .expect(401); - }); - - it('should return 401 when the user does not exist and sign up is disabled', async () => { - await orgRepository.update(current_organization.id, { enableSignUp: false }); - const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); - googleVerifyMock.mockImplementation(() => ({ - getPayload: () => ({ - sub: 'someSSOId', - email: 'ssoUser@tooljet.io', - name: 'SSO User', - hd: 'tooljet.io', - }), - })); - await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }) - .expect(401); - }); - - it('should return 401 when the user does not exist domain mismatch', async () => { - await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); - const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); - googleVerifyMock.mockImplementation(() => ({ - getPayload: () => ({ - sub: 'someSSOId', - email: 'ssoUser@tooljett.io', - name: 'SSO User', - hd: 'tooljet.io', - }), - })); - await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }) - .expect(401); - }); - - it('should return login info when the user does not exist and domain matches and sign up is enabled', async () => { - await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); - const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); - googleVerifyMock.mockImplementation(() => ({ - getPayload: () => ({ - sub: 'someSSOId', - email: 'ssoUser@tooljet.io', - name: 'SSO User', - hd: 'tooljet.io', - }), - })); - - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); - - expect(googleVerifyMock).toHaveBeenCalledWith({ - idToken: token, - audience: sso_configs.configs.clientId, + describe('Multi-Workspace', () => { + describe('sign in via Google OAuth', () => { + let sso_configs; + const token = 'some-Token'; + beforeEach(() => { + sso_configs = current_organization.ssoConfigs.find((conf) => conf.sso === 'google'); + }); + it('should return 401 if google sign in is disabled', async () => { + await ssoConfigsRepository.update(sso_configs.id, { enabled: false }); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); }); - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); - - const { - email, - first_name, - last_name, - admin, - group_permissions, - app_group_permissions, - organization_id, - organization, - } = response.body; - - expect(email).toEqual('ssoUser@tooljet.io'); - expect(first_name).toEqual('SSO'); - expect(last_name).toEqual('User'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - - it('should return login info when the user does not exist and sign up is enabled', async () => { - const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); - googleVerifyMock.mockImplementation(() => ({ - getPayload: () => ({ - sub: 'someSSOId', - email: 'ssoUser@tooljet.io', - name: 'SSO User', - hd: 'tooljet.io', - }), - })); - - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); - - expect(googleVerifyMock).toHaveBeenCalledWith({ - idToken: token, - audience: sso_configs.configs.clientId, + it('should return 401 when the user does not exist and sign up is disabled', async () => { + await orgRepository.update(current_organization.id, { enableSignUp: false }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); }); - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); - - const { - email, - first_name, - last_name, - admin, - group_permissions, - app_group_permissions, - organization_id, - organization, - } = response.body; - - expect(email).toEqual('ssoUser@tooljet.io'); - expect(first_name).toEqual('SSO'); - expect(last_name).toEqual('User'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - it('should return login info when the user does not exist and name not available and sign up is enabled', async () => { - const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); - googleVerifyMock.mockImplementation(() => ({ - getPayload: () => ({ - sub: 'someSSOId', - email: 'ssoUser@tooljet.io', - name: '', - hd: 'tooljet.io', - }), - })); - - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); - - expect(googleVerifyMock).toHaveBeenCalledWith({ - idToken: token, - audience: sso_configs.configs.clientId, + it('should return 401 when the user does not exist domain mismatch', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljett.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); }); - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); + it('should return login info when the user does not exist and domain matches and sign up is enabled', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); - const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = - response.body; + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); - expect(email).toEqual('ssoUser@tooljet.io'); - expect(first_name).toEqual('ssoUser'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - it('should return login info when the user exist', async () => { - await createUser(app, { - firstName: 'SSO', - lastName: 'userExist', - email: 'anotherUser1@tooljet.io', - groups: ['all_users'], - organization: current_organization, - status: 'active', + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUser@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('User'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); }); - const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); - googleVerifyMock.mockImplementation(() => ({ - getPayload: () => ({ - sub: 'someSSOId', + + it('should return login info when the user does not exist and sign up is enabled', async () => { + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUser@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('User'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user does not exist and name not available and sign up is enabled', async () => { + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: '', + hd: 'tooljet.io', + }), + })); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = + response.body; + + expect(email).toEqual('ssoUser@tooljet.io'); + expect(first_name).toEqual('ssoUser'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user exist', async () => { + await createUser(app, { + firstName: 'SSO', + lastName: 'userExist', email: 'anotherUser1@tooljet.io', - name: 'SSO User', - hd: 'tooljet.io', - }), - })); + groups: ['all_users'], + organization: current_organization, + status: 'active', + }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'anotherUser1@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); - expect(googleVerifyMock).toHaveBeenCalledWith({ - idToken: token, - audience: sso_configs.configs.clientId, + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('anotherUser1@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('userExist'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + }); + describe('sign in via Git OAuth', () => { + let sso_configs; + const token = 'some-Token'; + beforeEach(() => { + sso_configs = current_organization.ssoConfigs.find((conf) => conf.sso === 'git'); + }); + it('should return 401 if git sign in is disabled', async () => { + await ssoConfigsRepository.update(sso_configs.id, { enabled: false }); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); }); - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); + it('should return 401 when the user does not exist and sign up is disabled', async () => { + await orgRepository.update(current_organization.id, { enableSignUp: false }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); - const { - email, - first_name, - last_name, - admin, - group_permissions, - app_group_permissions, - organization_id, - organization, - } = response.body; + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); + }); - expect(email).toEqual('anotherUser1@tooljet.io'); - expect(first_name).toEqual('SSO'); - expect(last_name).toEqual('userExist'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); + it('should return 401 when the user does not exist domain mismatch', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljett.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); + }); + + it('should return login info when the user does not exist and domain matches and sign up is enabled', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('UserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + + it('should return login info when the user does not exist and domain includes spance matches and sign up is enabled', async () => { + await orgRepository.update(current_organization.id, { + domain: ' tooljet.io , tooljet.com, , , gmail.com', + }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('UserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + + it('should return login info when the user does not exist and sign up is enabled', async () => { + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('UserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user does not exist and name not available and sign up is enabled', async () => { + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: '', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = + response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('ssoUserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user does not exist and email id not available and sign up is enabled', async () => { + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: '', + email: '', + }; + }, + }; + }); + const gitGetUserEmailResponse = jest.fn(); + gitGetUserEmailResponse.mockImplementation(() => { + return { + json: () => { + return [ + { + email: 'ssoUserGit@tooljet.io', + primary: true, + verified: true, + }, + { + email: 'ssoUserGit2@tooljet.io', + primary: false, + verified: true, + }, + ]; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + mockedGot.mockImplementationOnce(gitGetUserEmailResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = + response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('ssoUserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user exist', async () => { + await createUser(app, { + firstName: 'SSO', + lastName: 'userExist', + email: 'anotherUser1@tooljet.io', + groups: ['all_users'], + organization: current_organization, + status: 'active', + }); + + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO userExist', + email: 'anotherUser1@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('anotherUser1@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('userExist'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); }); }); - describe('sign in via Git OAuth', () => { - let sso_configs; - const token = 'some-Token'; - beforeEach(() => { - sso_configs = current_organization.ssoConfigs.find((conf) => conf.sso === 'git'); + + describe('Multi-Workspace Disabled', () => { + beforeEach(async () => { + jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { + if (key === 'DISABLE_MULTI_WORKSPACE') { + return 'true'; + } else { + return process.env[key]; + } + }); }); - it('should return 401 if git sign in is disabled', async () => { - await ssoConfigsRepository.update(sso_configs.id, { enabled: false }); - await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }) - .expect(401); + describe('sign in via Google OAuth', () => { + let sso_configs; + const token = 'some-Token'; + beforeEach(() => { + sso_configs = current_organization.ssoConfigs.find((conf) => conf.sso === 'google'); + }); + it('should return 401 if google sign in is disabled', async () => { + await ssoConfigsRepository.update(sso_configs.id, { enabled: false }); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); + }); + + it('should return 401 when the user does not exist and sign up is disabled', async () => { + await orgRepository.update(current_organization.id, { enableSignUp: false }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); + }); + + it('should return 401 when the user does not exist domain mismatch', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljett.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); + }); + + it('should return login info when the user does not exist and domain matches and sign up is enabled', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUser@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('User'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + + it('should return login info when the user does not exist and sign up is enabled', async () => { + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUser@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('User'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user does not exist and name not available and sign up is enabled', async () => { + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'ssoUser@tooljet.io', + name: '', + hd: 'tooljet.io', + }), + })); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = + response.body; + + expect(email).toEqual('ssoUser@tooljet.io'); + expect(first_name).toEqual('ssoUser'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user exist', async () => { + await createUser(app, { + firstName: 'SSO', + lastName: 'userExist', + email: 'anotherUser1@tooljet.io', + groups: ['all_users'], + organization: current_organization, + status: 'active', + }); + const googleVerifyMock = jest.spyOn(OAuth2Client.prototype, 'verifyIdToken'); + googleVerifyMock.mockImplementation(() => ({ + getPayload: () => ({ + sub: 'someSSOId', + email: 'anotherUser1@tooljet.io', + name: 'SSO User', + hd: 'tooljet.io', + }), + })); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(googleVerifyMock).toHaveBeenCalledWith({ + idToken: token, + audience: sso_configs.configs.clientId, + }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('anotherUser1@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('userExist'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); }); - - it('should return 401 when the user does not exist and sign up is disabled', async () => { - await orgRepository.update(current_organization.id, { enableSignUp: false }); - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; + describe('sign in via Git OAuth', () => { + let sso_configs; + const token = 'some-Token'; + beforeEach(() => { + sso_configs = current_organization.ssoConfigs.find((conf) => conf.sso === 'git'); }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: 'SSO UserGit', - email: 'ssoUserGit@tooljet.io', - }; - }, - }; + it('should return 401 if git sign in is disabled', async () => { + await ssoConfigsRepository.update(sso_configs.id, { enabled: false }); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); }); - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); - await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }) - .expect(401); - }); - - it('should return 401 when the user does not exist domain mismatch', async () => { - await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; - }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: 'SSO UserGit', - email: 'ssoUserGit@tooljett.io', - }; - }, - }; - }); - - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); - - await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }) - .expect(401); - }); - - it('should return login info when the user does not exist and domain matches and sign up is enabled', async () => { - await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; - }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: 'SSO UserGit', - email: 'ssoUserGit@tooljet.io', - }; - }, - }; - }); - - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); - - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); - - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); - - const { - email, - first_name, - last_name, - admin, - group_permissions, - app_group_permissions, - organization_id, - organization, - } = response.body; - - expect(email).toEqual('ssoUserGit@tooljet.io'); - expect(first_name).toEqual('SSO'); - expect(last_name).toEqual('UserGit'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - - it('should return login info when the user does not exist and domain includes spance matches and sign up is enabled', async () => { - await orgRepository.update(current_organization.id, { - domain: ' tooljet.io , tooljet.com, , , gmail.com', - }); - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; - }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: 'SSO UserGit', - email: 'ssoUserGit@tooljet.io', - }; - }, - }; - }); - - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); - - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); - - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); - - const { - email, - first_name, - last_name, - admin, - group_permissions, - app_group_permissions, - organization_id, - organization, - } = response.body; - - expect(email).toEqual('ssoUserGit@tooljet.io'); - expect(first_name).toEqual('SSO'); - expect(last_name).toEqual('UserGit'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - - it('should return login info when the user does not exist and sign up is enabled', async () => { - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; - }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: 'SSO UserGit', - email: 'ssoUserGit@tooljet.io', - }; - }, - }; - }); - - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); - - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); - - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); - - const { - email, - first_name, - last_name, - admin, - group_permissions, - app_group_permissions, - organization_id, - organization, - } = response.body; - - expect(email).toEqual('ssoUserGit@tooljet.io'); - expect(first_name).toEqual('SSO'); - expect(last_name).toEqual('UserGit'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - it('should return login info when the user does not exist and name not available and sign up is enabled', async () => { - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; - }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: '', - email: 'ssoUserGit@tooljet.io', - }; - }, - }; - }); - - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); - - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); - - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); - - const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = - response.body; - - expect(email).toEqual('ssoUserGit@tooljet.io'); - expect(first_name).toEqual('ssoUserGit'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - it('should return login info when the user does not exist and email id not available and sign up is enabled', async () => { - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; - }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: '', - email: '', - }; - }, - }; - }); - const gitGetUserEmailResponse = jest.fn(); - gitGetUserEmailResponse.mockImplementation(() => { - return { - json: () => { - return [ - { + it('should return 401 when the user does not exist and sign up is disabled', async () => { + await orgRepository.update(current_organization.id, { enableSignUp: false }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', email: 'ssoUserGit@tooljet.io', - primary: true, - verified: true, - }, - { - email: 'ssoUserGit2@tooljet.io', - primary: false, - verified: true, - }, - ]; - }, - }; + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); }); - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); - mockedGot.mockImplementationOnce(gitGetUserEmailResponse); + it('should return 401 when the user does not exist domain mismatch', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljett.io', + }; + }, + }; + }); - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); - - const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = - response.body; - - expect(email).toEqual('ssoUserGit@tooljet.io'); - expect(first_name).toEqual('ssoUserGit'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); - }); - it('should return login info when the user exist', async () => { - await createUser(app, { - firstName: 'SSO', - lastName: 'userExist', - email: 'anotherUser1@tooljet.io', - groups: ['all_users'], - organization: current_organization, - status: 'active', + await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }) + .expect(401); }); - const gitAuthResponse = jest.fn(); - gitAuthResponse.mockImplementation(() => { - return { - json: () => { - return { - access_token: 'some-access-token', - scope: 'scope', - token_type: 'bearer', - }; - }, - }; - }); - const gitGetUserResponse = jest.fn(); - gitGetUserResponse.mockImplementation(() => { - return { - json: () => { - return { - name: 'SSO userExist', - email: 'anotherUser1@tooljet.io', - }; - }, - }; + it('should return login info when the user does not exist and domain matches and sign up is enabled', async () => { + await orgRepository.update(current_organization.id, { domain: 'tooljet.io,tooljet.com' }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('UserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); }); - mockedGot.mockImplementationOnce(gitAuthResponse); - mockedGot.mockImplementationOnce(gitGetUserResponse); + it('should return login info when the user does not exist and domain includes spance matches and sign up is enabled', async () => { + await orgRepository.update(current_organization.id, { + domain: ' tooljet.io , tooljet.com, , , gmail.com', + }); + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); - const response = await request(app.getHttpServer()) - .post('/api/oauth/sign-in/' + sso_configs.id) - .send({ token }); + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); - expect(response.statusCode).toBe(201); - expect(Object.keys(response.body).sort()).toEqual( - [ - 'id', - 'email', - 'first_name', - 'last_name', - 'auth_token', - 'admin', - 'organization_id', - 'organization', - 'group_permissions', - 'app_group_permissions', - ].sort() - ); + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); - const { - email, - first_name, - last_name, - admin, - group_permissions, - app_group_permissions, - organization_id, - organization, - } = response.body; + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); - expect(email).toEqual('anotherUser1@tooljet.io'); - expect(first_name).toEqual('SSO'); - expect(last_name).toEqual('userExist'); - expect(admin).toBeFalsy(); - expect(organization_id).toBe(current_organization.id); - expect(organization).toBe(current_organization.name); - expect(group_permissions).toHaveLength(1); - expect(group_permissions[0].group).toEqual('all_users'); - expect(Object.keys(group_permissions[0]).sort()).toEqual( - [ - 'id', - 'organization_id', - 'group', - 'app_create', - 'app_delete', - 'updated_at', - 'created_at', - 'folder_create', - ].sort() - ); - expect(app_group_permissions).toHaveLength(0); + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('UserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + + it('should return login info when the user does not exist and sign up is enabled', async () => { + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO UserGit', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('UserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user does not exist and name not available and sign up is enabled', async () => { + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: '', + email: 'ssoUserGit@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = + response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('ssoUserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user does not exist and email id not available and sign up is enabled', async () => { + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: '', + email: '', + }; + }, + }; + }); + const gitGetUserEmailResponse = jest.fn(); + gitGetUserEmailResponse.mockImplementation(() => { + return { + json: () => { + return [ + { + email: 'ssoUserGit@tooljet.io', + primary: true, + verified: true, + }, + { + email: 'ssoUserGit2@tooljet.io', + primary: false, + verified: true, + }, + ]; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + mockedGot.mockImplementationOnce(gitGetUserEmailResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { email, first_name, admin, group_permissions, app_group_permissions, organization_id, organization } = + response.body; + + expect(email).toEqual('ssoUserGit@tooljet.io'); + expect(first_name).toEqual('ssoUserGit'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); + it('should return login info when the user exist', async () => { + await createUser(app, { + firstName: 'SSO', + lastName: 'userExist', + email: 'anotherUser1@tooljet.io', + groups: ['all_users'], + organization: current_organization, + status: 'active', + }); + + const gitAuthResponse = jest.fn(); + gitAuthResponse.mockImplementation(() => { + return { + json: () => { + return { + access_token: 'some-access-token', + scope: 'scope', + token_type: 'bearer', + }; + }, + }; + }); + const gitGetUserResponse = jest.fn(); + gitGetUserResponse.mockImplementation(() => { + return { + json: () => { + return { + name: 'SSO userExist', + email: 'anotherUser1@tooljet.io', + }; + }, + }; + }); + + mockedGot.mockImplementationOnce(gitAuthResponse); + mockedGot.mockImplementationOnce(gitGetUserResponse); + + const response = await request(app.getHttpServer()) + .post('/api/oauth/sign-in/' + sso_configs.id) + .send({ token }); + + expect(response.statusCode).toBe(201); + expect(Object.keys(response.body).sort()).toEqual( + [ + 'id', + 'email', + 'first_name', + 'last_name', + 'auth_token', + 'admin', + 'organization_id', + 'organization', + 'group_permissions', + 'app_group_permissions', + ].sort() + ); + + const { + email, + first_name, + last_name, + admin, + group_permissions, + app_group_permissions, + organization_id, + organization, + } = response.body; + + expect(email).toEqual('anotherUser1@tooljet.io'); + expect(first_name).toEqual('SSO'); + expect(last_name).toEqual('userExist'); + expect(admin).toBeFalsy(); + expect(organization_id).toBe(current_organization.id); + expect(organization).toBe(current_organization.name); + expect(group_permissions).toHaveLength(1); + expect(group_permissions[0].group).toEqual('all_users'); + expect(Object.keys(group_permissions[0]).sort()).toEqual( + [ + 'id', + 'organization_id', + 'group', + 'app_create', + 'app_delete', + 'updated_at', + 'created_at', + 'folder_create', + ].sort() + ); + expect(app_group_permissions).toHaveLength(0); + }); }); }); }); diff --git a/server/test/controllers/organizations.e2e-spec.ts b/server/test/controllers/organizations.e2e-spec.ts index 98e9f842cd..972e182c6a 100644 --- a/server/test/controllers/organizations.e2e-spec.ts +++ b/server/test/controllers/organizations.e2e-spec.ts @@ -13,14 +13,6 @@ describe('organizations controller', () => { beforeEach(async () => { await clearDB(); - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'MULTI_ORGANIZATION': - return 'false'; - default: - return process.env[key]; - } - }); }); beforeAll(async () => { @@ -65,28 +57,20 @@ describe('organizations controller', () => { describe('create organization', () => { it('should allow only authenticated users to create organization', async () => { - await request(app.getHttpServer()).post('/api/organizations').send({ name: 'My organization' }).expect(401); + await request(app.getHttpServer()).post('/api/organizations').send({ name: 'My workspace' }).expect(401); }); - it('should create new organization if multi organization supported', async () => { - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); + it('should create new organization if Multi-Workspace supported', async () => { const { user, organization } = await createUser(app, { email: 'admin@tooljet.io', }); const response = await request(app.getHttpServer()) .post('/api/organizations') - .send({ name: 'My organization' }) + .send({ name: 'My workspace' }) .set('Authorization', authHeaderForUser(user)); expect(response.statusCode).toBe(201); expect(response.body.organization_id).not.toBe(organization.id); - expect(response.body.organization).toBe('My organization'); + expect(response.body.organization).toBe('My workspace'); expect(response.body.admin).toBeTruthy(); const newUser = await userRepository.findOneOrFail({ where: { id: user.id } }); @@ -94,14 +78,6 @@ describe('organizations controller', () => { }); it('should throw error if name is empty', async () => { - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); const { user } = await createUser(app, { email: 'admin@tooljet.io' }); const response = await request(app.getHttpServer()) .post('/api/organizations') @@ -111,35 +87,35 @@ describe('organizations controller', () => { expect(response.statusCode).toBe(400); }); - it('should not create new organization if multi organization not supported', async () => { - const { user } = await createUser(app, { email: 'admin@tooljet.io' }); - await request(app.getHttpServer()) - .post('/api/organizations') - .send({ name: 'My organization' }) - .set('Authorization', authHeaderForUser(user)) - .expect(403); - }); - - it('should create new organization if multi organization supported and user logged in via SSO', async () => { + it('should not create new organization if Multi-Workspace not supported', async () => { jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { switch (key) { - case 'MULTI_ORGANIZATION': + case 'DISABLE_MULTI_WORKSPACE': return 'true'; default: return process.env[key]; } }); + const { user } = await createUser(app, { email: 'admin@tooljet.io' }); + await request(app.getHttpServer()) + .post('/api/organizations') + .send({ name: 'My workspace' }) + .set('Authorization', authHeaderForUser(user)) + .expect(403); + }); + + it('should create new organization if Multi-Workspace supported and user logged in via SSO', async () => { const { user, organization } = await createUser(app, { email: 'admin@tooljet.io', }); const response = await request(app.getHttpServer()) .post('/api/organizations') - .send({ name: 'My organization' }) + .send({ name: 'My workspace' }) .set('Authorization', authHeaderForUser(user, null, false)); expect(response.statusCode).toBe(201); expect(response.body.organization_id).not.toBe(organization.id); - expect(response.body.organization).toBe('My organization'); + expect(response.body.organization).toBe('My workspace'); expect(response.body.admin).toBeTruthy(); }); }); @@ -252,6 +228,14 @@ describe('organizations controller', () => { describe('get public organization configs', () => { it('should get organization details for all users for single organization', async () => { + jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { + switch (key) { + case 'DISABLE_MULTI_WORKSPACE': + return 'true'; + default: + return process.env[key]; + } + }); const { user } = await createUser(app, { email: 'admin@tooljet.io', }); @@ -291,14 +275,6 @@ describe('organizations controller', () => { }); it('should get organization specific details for all users for multiple organization deployment', async () => { - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); const { user, organization } = await createUser(app, { email: 'admin@tooljet.io', }); diff --git a/server/test/controllers/users.e2e-spec.ts b/server/test/controllers/users.e2e-spec.ts index 975ad27312..26d4b23774 100644 --- a/server/test/controllers/users.e2e-spec.ts +++ b/server/test/controllers/users.e2e-spec.ts @@ -12,22 +12,17 @@ describe('users controller', () => { beforeEach(async () => { await clearDB(); - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'DISABLE_SIGNUPS': - return 'false'; - case 'MULTI_ORGANIZATION': - return 'false'; - default: - return process.env[key]; - } - }); }); beforeAll(async () => { ({ app, mockConfig } = await createNestAppInstanceWithEnvMock()); }); + afterEach(() => { + jest.resetAllMocks(); + jest.clearAllMocks(); + }); + describe('PATCH /api/users/change_password', () => { it('should allow users to update their password', async () => { const userData = await createUser(app, { email: 'admin@tooljet.io' }); @@ -87,17 +82,7 @@ describe('users controller', () => { }); describe('POST /api/users/set_password_from_token', () => { - it('should allow users to setup account after sign up using multi organization', async () => { - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'DISABLE_SIGNUPS': - return 'false'; - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); + it('should allow users to setup account after sign up using Multi-Workspace', async () => { const invitationToken = uuidv4(); const userData = await createUser(app, { email: 'signup@tooljet.io', @@ -125,17 +110,7 @@ describe('users controller', () => { expect(organizationUser.status).toEqual('active'); }); - it('should return error if required params are not present - multi organization', async () => { - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'DISABLE_SIGNUPS': - return 'false'; - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); + it('should return error if required params are not present - Multi-Workspace', async () => { const invitationToken = uuidv4(); await createUser(app, { email: 'signup@tooljet.io', @@ -155,6 +130,14 @@ describe('users controller', () => { }); it('should not allow users to setup account for single organization', async () => { + jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { + switch (key) { + case 'DISABLE_MULTI_WORKSPACE': + return 'true'; + default: + return process.env[key]; + } + }); const invitationToken = uuidv4(); await createUser(app, { email: 'signup@tooljet.io', @@ -174,13 +157,11 @@ describe('users controller', () => { expect(response.statusCode).toBe(403); }); - it('should not allow users to setup account for multi organization and sign up disabled', async () => { + it('should not allow users to setup account for Multi-Workspace and sign up disabled', async () => { jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { switch (key) { case 'DISABLE_SIGNUPS': return 'true'; - case 'MULTI_ORGANIZATION': - return 'true'; default: return process.env[key]; } @@ -216,15 +197,6 @@ describe('users controller', () => { organization: org, }); - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); - const signUpResponse = await request(app.getHttpServer()) .post('/api/signup') .send({ email: 'invited@tooljet.io' }); @@ -269,15 +241,6 @@ describe('users controller', () => { organization: org, }); - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); - const signUpResponse = await request(app.getHttpServer()) .post('/api/signup') .send({ email: 'invited@tooljet.io' }); @@ -321,15 +284,7 @@ describe('users controller', () => { }); describe('POST /api/users/accept-invite', () => { - it('should allow users to accept invitation when multi organization is enabled', async () => { - jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { - switch (key) { - case 'MULTI_ORGANIZATION': - return 'true'; - default: - return process.env[key]; - } - }); + it('should allow users to accept invitation when Multi-Workspace is enabled', async () => { const userData = await createUser(app, { email: 'organizationUser@tooljet.io', status: 'invited', @@ -347,11 +302,11 @@ describe('users controller', () => { expect(organizationUser.status).toEqual('active'); }); - it('should allow users to accept invitation when multi organization is disabled', async () => { + it('should allow users to accept invitation when Multi-Workspace is disabled', async () => { jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => { switch (key) { - case 'MULTI_ORGANIZATION': - return 'false'; + case 'DISABLE_MULTI_WORKSPACE': + return 'true'; default: return process.env[key]; }