mirror of
https://github.com/ToolJet/ToolJet
synced 2026-04-21 13:37:28 +00:00
Relabelling organization with workspace (#2992)
* Relabelling organization with workspace * placeholder fix * Bug fixes * fix * firefox issue fix
This commit is contained in:
parent
863f91c77b
commit
e656ea9259
27 changed files with 1934 additions and 1068 deletions
|
|
@ -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=
|
||||
|
|
|
|||
6
app.json
6
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"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
| ------------------ | ----------------------------------------- |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ title: GitHub
|
|||
|
||||
# GitHub Single Sign-on
|
||||
|
||||
Select `Manage SSO` from organization options
|
||||
Select `Manage SSO` from workspace options
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ title: Google
|
|||
|
||||
# Google Single Sign-on
|
||||
|
||||
Select `Manage SSO` from organization options
|
||||
Select `Manage SSO` from workspace options
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ Go to [Google cloud console](https://console.cloud.google.com/) and create a pro
|
|||
|
||||
</div>
|
||||
|
||||
- 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'.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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**.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -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
|
|||
|
||||
</div>
|
||||
|
||||
- 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**.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -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**.
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -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. |
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
@ -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. |
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class ConfirmationPage extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Organization</label>
|
||||
<label className="form-label">Workspace</label>
|
||||
<div className="input-group input-group-flat">
|
||||
<input
|
||||
onChange={this.handleChange}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class OrganizationInvitationPage extends React.Component {
|
|||
isLoading: false,
|
||||
};
|
||||
this.formRef = React.createRef(null);
|
||||
this.single_organization = window.public_config?.MULTI_ORGANIZATION !== 'true';
|
||||
this.single_organization = window.public_config?.DISABLE_MULTI_WORKSPACE === 'true';
|
||||
}
|
||||
|
||||
handleChange = (event) => {
|
||||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ class ManageAppUsers extends React.Component {
|
|||
|
||||
<Modal.Footer>
|
||||
<a href="/users" target="_blank" className="btn color-primary mt-3">
|
||||
Manage Organization Users
|
||||
Manage Users
|
||||
</a>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
) : (
|
||||
<div className="card-body">
|
||||
{!configs && <div className="text-center">No login methods enabled for this organization</div>}
|
||||
{!configs && <div className="text-center">No login methods enabled for this workspace</div>}
|
||||
{configs?.form?.enabled && (
|
||||
<div>
|
||||
<h2 className="card-title text-center mb-4" data-cy="login-page-header">
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export function Google({ settings, updateData }) {
|
|||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="Enter Client Secret"
|
||||
placeholder="Enter Client Id"
|
||||
value={clientId}
|
||||
onChange={(e) => setClientId(e.target.value)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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() {
|
|||
</div>
|
||||
{!isSingleOrganization && (
|
||||
<div className="dropdown-item org-actions">
|
||||
<div onClick={showCreateModal}>Add Organizations</div>
|
||||
<div onClick={showCreateModal}>Add workspace</div>
|
||||
</div>
|
||||
)}
|
||||
{admin && (
|
||||
|
|
@ -281,8 +284,12 @@ export const Organization = function Organization() {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<div className="dropdown organization-list" onMouseEnter={() => setIsListOrganizations(false)}>
|
||||
<a href="#" className={`btn ${!isSingleOrganization || admin ? 'dropdown-toggle' : ''}`}>
|
||||
<div className="dropdown organization-list">
|
||||
<a
|
||||
href="#"
|
||||
className={`btn ${!isSingleOrganization || admin ? 'dropdown-toggle' : ''}`}
|
||||
onMouseOver={() => setIsListOrganizations(false)}
|
||||
>
|
||||
<div>{organization}</div>
|
||||
</a>
|
||||
{(!isSingleOrganization || admin) && (
|
||||
|
|
@ -291,14 +298,14 @@ export const Organization = function Organization() {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Modal show={showCreateOrg} closeModal={() => setShowCreateOrg(false)} title="Create organization">
|
||||
<Modal show={showCreateOrg} closeModal={() => setShowCreateOrg(false)} title="Create workspace">
|
||||
<div className="row">
|
||||
<div className="col modal-main">
|
||||
<input
|
||||
type="text"
|
||||
onChange={(e) => 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
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal show={showEditOrg} closeModal={() => setShowEditOrg(false)} title="Edit organization">
|
||||
<Modal show={showEditOrg} closeModal={() => setShowEditOrg(false)} title="Edit workspace">
|
||||
<div className="row">
|
||||
<div className="col modal-main">
|
||||
<input
|
||||
type="text"
|
||||
onChange={(e) => setNewOrgName(e.target.value)}
|
||||
className="form-control"
|
||||
placeholder="organization name"
|
||||
placeholder="workspace name"
|
||||
disabled={isCreating}
|
||||
value={newOrgName}
|
||||
maxLength={25}
|
||||
|
|
|
|||
|
|
@ -63,12 +63,12 @@ export class OauthService {
|
|||
async #findAndActivateUser(email: string, organizationId: string): Promise<User> {
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export class OrganizationsController {
|
|||
|
||||
@Get(['/:organizationId/public-configs', '/public-configs'])
|
||||
async getOrganizationDetails(@Param('organizationId') organizationId: string) {
|
||||
if (!organizationId && this.configService.get<string>('MULTI_ORGANIZATION') !== 'true') {
|
||||
if (!organizationId && this.configService.get<string>('DISABLE_MULTI_WORKSPACE') === 'true') {
|
||||
// Request from single organization login page - find one from organization and setting
|
||||
organizationId = (await this.organizationsService.getSingleOrganization()).id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@ export class MultiOrganizationGuard implements CanActivate {
|
|||
constructor(private configService: ConfigService) {}
|
||||
|
||||
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
|
||||
return this.configService.get<string>('MULTI_ORGANIZATION') === 'true';
|
||||
return this.configService.get<string>('DISABLE_MULTI_WORKSPACE') !== 'true';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export class AppConfigService {
|
|||
'SENTRY_DNS',
|
||||
'SENTRY_DEBUG',
|
||||
'DISABLE_SIGNUPS',
|
||||
'MULTI_ORGANIZATION',
|
||||
'DISABLE_MULTI_WORKSPACE',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export class AuthService {
|
|||
if (!organizationId) {
|
||||
// Global login
|
||||
// Determine the organization to be loaded
|
||||
if (this.configService.get<string>('MULTI_ORGANIZATION') !== 'true') {
|
||||
if (this.configService.get<string>('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<string>('MULTI_ORGANIZATION') !== 'true') {
|
||||
if (this.configService.get<string>('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<string>('MULTI_ORGANIZATION') !== 'true') {
|
||||
if (this.configService.get<string>('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);
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export class EmailService {
|
|||
<p>Hi ${name || ''},</p>
|
||||
<br>
|
||||
<span>
|
||||
${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.
|
||||
</span>
|
||||
<br>
|
||||
<a href="${inviteUrl}">${inviteUrl}</a>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export class SeedsService {
|
|||
sso: 'form',
|
||||
},
|
||||
],
|
||||
name: 'My organization',
|
||||
name: 'My workspace',
|
||||
});
|
||||
|
||||
await manager.save(organization);
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue