mirror of
https://github.com/ToolJet/ToolJet
synced 2026-04-21 13:37:28 +00:00
SSO for GitHub Enterprise self hosted (#3352)
* SSO for GitHub Enterprise self hosted * changes * test cases * fixes * label fix * fixes * readme changes
This commit is contained in:
parent
0055773ad0
commit
b710d7b02e
17 changed files with 556 additions and 49 deletions
|
|
@ -53,5 +53,6 @@ ENABLE_MULTIPLAYER_EDITING=true
|
|||
SSO_GOOGLE_OAUTH2_CLIENT_ID=
|
||||
SSO_GIT_OAUTH2_CLIENT_ID=
|
||||
SSO_GIT_OAUTH2_CLIENT_SECRET=
|
||||
SSO_GIT_OAUTH2_HOST=
|
||||
SSO_ACCEPTED_DOMAINS=
|
||||
SSO_DISABLE_SIGNUPS=
|
||||
|
|
@ -49,6 +49,7 @@ SSO_RESTRICTED_DOMAIN=
|
|||
SSO_GOOGLE_OAUTH2_CLIENT_ID=
|
||||
SSO_GIT_OAUTH2_CLIENT_ID=
|
||||
SSO_GIT_OAUTH2_CLIENT_SECRET=
|
||||
SSO_GIT_OAUTH2_HOST=
|
||||
|
||||
#TELEMETRY
|
||||
DEPLOYMENT_PLATFORM=docker
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ Configurations for instance level SSO. Valid only if `DISABLE_MULTI_WORKSPACE` i
|
|||
| SSO_GOOGLE_OAUTH2_CLIENT_ID | Google OAuth client id |
|
||||
| SSO_GIT_OAUTH2_CLIENT_ID | GitHub OAuth client id |
|
||||
| SSO_GIT_OAUTH2_CLIENT_SECRET | GitHub OAuth client secret |
|
||||
| SSO_GIT_OAUTH2_HOST | GitHub OAuth host name if GitHub is self hosted |
|
||||
| SSO_ACCEPTED_DOMAINS | comma separated email domains that supports SSO authentication |
|
||||
| SSO_DISABLE_SIGNUPS | Disable user sign up if authenticated user does not exist |
|
||||
|
||||
|
|
|
|||
|
|
@ -56,3 +56,18 @@ Go to [GitHub Developer settings](https://github.com/settings/developers) and na
|
|||
Lastly, enter `Client Id` and `Client Secret` in GitHub manage SSO page and save.
|
||||
|
||||
The GitHub sign-in button will now be available in your ToolJet login screen if you have not enabled Multi-Workspace.
|
||||
|
||||
:::info
|
||||
Should configure `Host Name` if you are using GitHub Enterprise self hosted. Host name should be a URL and should not ends with `/`, example: `https://github.tooljet.com`
|
||||
:::
|
||||
|
||||
## Multi-Workspace
|
||||
If you have enabled Multi-Workspace you can configure GitHub SSO as mentioned above, for setting default SSO for the instance use environment variable.
|
||||
|
||||
| variable | description |
|
||||
| ------------------------------------- | ----------------------------------------------------------- |
|
||||
| SSO_GIT_OAUTH2_CLIENT_ID | GitHub OAuth client id |
|
||||
| SSO_GIT_OAUTH2_CLIENT_SECRET | GitHub OAuth client secret |
|
||||
| SSO_GIT_OAUTH2_HOST | GitHub OAuth host name if GitHub is self hosted |
|
||||
|
||||
Redirect URL should be `<host>/sso/git`
|
||||
|
|
@ -83,3 +83,12 @@ 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 Multi-Workspace.
|
||||
|
||||
## Multi-Workspace
|
||||
If you have enabled Multi-Workspace you can configure Google SSO as mentioned above, for setting default SSO for the instance use environment variable.
|
||||
|
||||
| variable | description |
|
||||
| ------------------------------------- | ----------------------------------------------------------- |
|
||||
| SSO_GOOGLE_OAUTH2_CLIENT_ID | Google OAuth client id |
|
||||
|
||||
Redirect URL should be `<host>/sso/google`
|
||||
|
|
|
|||
BIN
docs/static/img/sso/git/manage-sso-1.png
vendored
BIN
docs/static/img/sso/git/manage-sso-1.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 48 KiB |
BIN
docs/static/img/sso/git/manage-sso-2.png
vendored
BIN
docs/static/img/sso/git/manage-sso-2.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 585 KiB After Width: | Height: | Size: 60 KiB |
|
|
@ -4,7 +4,7 @@ import { buildURLWithQuery } from '@/_helpers/utils';
|
|||
export default function GitSSOLoginButton({ configs, text }) {
|
||||
const gitLogin = (e) => {
|
||||
e.preventDefault();
|
||||
window.location.href = buildURLWithQuery('https://github.com/login/oauth/authorize', {
|
||||
window.location.href = buildURLWithQuery(`${configs.host_name || 'https://github.com'}/login/oauth/authorize`, {
|
||||
client_id: configs?.client_id,
|
||||
scope: 'user:email',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class LoginPage extends React.Component {
|
|||
enabled: !!window.public_config?.SSO_GIT_OAUTH2_CLIENT_ID,
|
||||
configs: {
|
||||
client_id: window.public_config?.SSO_GIT_OAUTH2_CLIENT_ID,
|
||||
host_name: window.public_config?.SSO_GIT_OAUTH2_HOST,
|
||||
},
|
||||
},
|
||||
form: {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { copyToClipboard } from '@/_helpers/appUtils';
|
|||
export function Git({ settings, updateData }) {
|
||||
const [enabled, setEnabled] = useState(settings?.enabled || false);
|
||||
const [clientId, setClientId] = useState(settings?.configs?.client_id || '');
|
||||
const [hostName, setHostName] = useState(settings?.configs?.host_name || '');
|
||||
const [clientSecret, setClientSecret] = useState(settings?.configs?.client_secret || '');
|
||||
const [isSaving, setSaving] = useState(false);
|
||||
const [configId, setConfigId] = useState(settings?.id);
|
||||
|
|
@ -13,6 +14,7 @@ export function Git({ settings, updateData }) {
|
|||
const reset = () => {
|
||||
setClientId(settings?.configs?.client_id || '');
|
||||
setClientSecret(settings?.configs?.client_secret || '');
|
||||
setHostName(settings?.configs?.host_name || '');
|
||||
};
|
||||
|
||||
const copyFunction = (input) => {
|
||||
|
|
@ -21,11 +23,14 @@ export function Git({ settings, updateData }) {
|
|||
};
|
||||
const saveSettings = () => {
|
||||
setSaving(true);
|
||||
organizationService.editOrganizationConfigs({ type: 'git', configs: { clientId, clientSecret } }).then(
|
||||
organizationService.editOrganizationConfigs({ type: 'git', configs: { clientId, clientSecret, hostName } }).then(
|
||||
(data) => {
|
||||
setSaving(false);
|
||||
data.id && setConfigId(data.id);
|
||||
updateData('git', { id: data.id, configs: { client_id: clientId, client_secret: clientSecret } });
|
||||
updateData('git', {
|
||||
id: data.id,
|
||||
configs: { client_id: clientId, client_secret: clientSecret, host_name: hostName },
|
||||
});
|
||||
toast.success('updated SSO configurations', {
|
||||
position: 'top-center',
|
||||
});
|
||||
|
|
@ -86,6 +91,24 @@ export function Git({ settings, updateData }) {
|
|||
</div>
|
||||
<div className="card-body">
|
||||
<form noValidate>
|
||||
<div className="form-group mb-3">
|
||||
<label className="form-label" data-cy="host-name-label">
|
||||
Host Name
|
||||
</label>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="Enter Host Name"
|
||||
value={hostName}
|
||||
onChange={(e) => setHostName(e.target.value)}
|
||||
data-cy="host-name-input"
|
||||
/>
|
||||
</div>
|
||||
<div className="help-text mt-2">
|
||||
<div data-cy="general-settings-help-text">Required if GitHub is self hosted</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group mb-3">
|
||||
<label className="form-label" data-cy="client-id-label">
|
||||
Client Id
|
||||
|
|
|
|||
|
|
@ -1,17 +1,22 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import got from 'got';
|
||||
import UserResponse from './models/user_response';
|
||||
|
||||
@Injectable()
|
||||
export class GitOAuthService {
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
private readonly authUrl = 'https://github.com/login/oauth/access_token';
|
||||
private readonly getUserUrl = 'https://api.github.com/user';
|
||||
private readonly getUserEmailUrl = 'https://api.github.com/user/emails';
|
||||
private readonly authUrl = '/login/oauth/access_token';
|
||||
|
||||
async #getUserDetails({ access_token }: AuthResponse): Promise<UserResponse> {
|
||||
const response: any = await got(this.getUserUrl, {
|
||||
#getAuthUrl(hostName) {
|
||||
return `${hostName || 'https://github.com'}${this.authUrl}`;
|
||||
}
|
||||
#getUserUrl(hostName) {
|
||||
return `${hostName ? `${hostName}/api/v3` : 'https://github.com'}/user`;
|
||||
}
|
||||
#getUserEmailUrl(hostName) {
|
||||
return `${hostName ? `${hostName}/api/v3` : 'https://github.com'}/user/emails`;
|
||||
}
|
||||
async #getUserDetails({ access_token }: AuthResponse, hostName: string): Promise<UserResponse> {
|
||||
const response: any = await got(this.#getUserUrl(hostName), {
|
||||
method: 'get',
|
||||
headers: { Accept: 'application/json', Authorization: `token ${access_token}` },
|
||||
}).json();
|
||||
|
|
@ -24,14 +29,14 @@ export class GitOAuthService {
|
|||
|
||||
if (!email) {
|
||||
// email visibility not set to public
|
||||
email = await this.#getEmailId(access_token);
|
||||
email = await this.#getEmailId(access_token, hostName);
|
||||
}
|
||||
|
||||
return { userSSOId: access_token, firstName, lastName, email, sso: 'git' };
|
||||
}
|
||||
|
||||
async #getEmailId(access_token: string) {
|
||||
const response: any = await got(this.getUserEmailUrl, {
|
||||
async #getEmailId(access_token: string, hostName: string) {
|
||||
const response: any = await got(this.#getUserEmailUrl(hostName), {
|
||||
method: 'get',
|
||||
headers: { Accept: 'application/json', Authorization: `token ${access_token}` },
|
||||
}).json();
|
||||
|
|
@ -40,13 +45,13 @@ export class GitOAuthService {
|
|||
}
|
||||
|
||||
async signIn(code: string, configs: any): Promise<any> {
|
||||
const response: any = await got(this.authUrl, {
|
||||
const response: any = await got(this.#getAuthUrl(configs.hostName), {
|
||||
method: 'post',
|
||||
headers: { Accept: 'application/json' },
|
||||
json: { client_id: configs.clientId, client_secret: configs.clientSecret, code },
|
||||
}).json();
|
||||
|
||||
return await this.#getUserDetails(response);
|
||||
return await this.#getUserDetails(response, configs.hostName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ export class OauthService {
|
|||
configs: {
|
||||
clientId: this.configService.get<string>('SSO_GIT_OAUTH2_CLIENT_ID'),
|
||||
clientSecret: this.configService.get<string>('SSO_GIT_OAUTH2_CLIENT_SECRET'),
|
||||
hostName: this.configService.get<string>('SSO_GIT_OAUTH2_HOST'),
|
||||
},
|
||||
};
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ type Google = {
|
|||
type Git = {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
hostName?: string;
|
||||
};
|
||||
@Entity({ name: 'sso_configs' })
|
||||
export class SSOConfigs {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export class AppConfigService {
|
|||
'DISABLE_MULTI_WORKSPACE',
|
||||
'SSO_GOOGLE_OAUTH2_CLIENT_ID',
|
||||
'SSO_GIT_OAUTH2_CLIENT_ID',
|
||||
'SSO_GIT_OAUTH2_HOST',
|
||||
'SSO_DISABLE_SIGNUPS',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,6 +250,12 @@ export class OrganizationsService {
|
|||
enabled: true,
|
||||
configs: {
|
||||
clientId: this.configService.get<string>('SSO_GIT_OAUTH2_CLIENT_ID'),
|
||||
clientSecret: await this.encryptionService.encryptColumnValue(
|
||||
'ssoConfigs',
|
||||
'clientSecret',
|
||||
this.configService.get<string>('SSO_GIT_OAUTH2_CLIENT_SECRET')
|
||||
),
|
||||
hostName: this.configService.get<string>('SSO_GIT_OAUTH2_HOST'),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -858,6 +858,174 @@ describe('oauth controller', () => {
|
|||
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(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
await orgUser.reload();
|
||||
expect(orgUser.status).toEqual('active');
|
||||
});
|
||||
it('Common login - should return login info when the user exist and hostname exist in configs', async () => {
|
||||
jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => {
|
||||
switch (key) {
|
||||
case 'SSO_GOOGLE_OAUTH2_CLIENT_ID':
|
||||
return 'google-client-id';
|
||||
case 'SSO_GIT_OAUTH2_CLIENT_ID':
|
||||
return 'git-client-id';
|
||||
case 'SSO_GIT_OAUTH2_CLIENT_SECRET':
|
||||
return 'git-secret';
|
||||
case 'SSO_GIT_OAUTH2_HOST':
|
||||
return 'https://github.host.com';
|
||||
default:
|
||||
return process.env[key];
|
||||
}
|
||||
});
|
||||
|
||||
const { orgUser } = await createUser(app, {
|
||||
firstName: 'SSO',
|
||||
lastName: 'userExist',
|
||||
email: 'anotherUser1@tooljet.io',
|
||||
groups: ['all_users'],
|
||||
organization: current_organization,
|
||||
});
|
||||
|
||||
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/common/git').send({ token });
|
||||
|
||||
expect(response.statusCode).toBe(201);
|
||||
|
||||
expect(gitAuthResponse).toBeCalledWith('https://github.host.com/login/oauth/access_token', expect.anything());
|
||||
expect(gitGetUserResponse).toBeCalledWith('https://github.host.com/api/v3/user', expect.anything());
|
||||
expect(Object.keys(response.body).sort()).toEqual(authResponseKeys);
|
||||
|
||||
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(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
await orgUser.reload();
|
||||
expect(orgUser.status).toEqual('active');
|
||||
});
|
||||
it('Workspace login - should return login info when the user exist and hostname exist in configs', async () => {
|
||||
jest.spyOn(mockConfig, 'get').mockImplementation((key: string) => {
|
||||
switch (key) {
|
||||
case 'SSO_GOOGLE_OAUTH2_CLIENT_ID':
|
||||
return 'google-client-id';
|
||||
case 'SSO_GIT_OAUTH2_CLIENT_ID':
|
||||
return 'git-client-id';
|
||||
case 'SSO_GIT_OAUTH2_CLIENT_SECRET':
|
||||
return 'git-secret';
|
||||
case 'SSO_GIT_OAUTH2_HOST':
|
||||
return 'https://github.host.com';
|
||||
default:
|
||||
return process.env[key];
|
||||
}
|
||||
});
|
||||
|
||||
const { orgUser } = await createUser(app, {
|
||||
firstName: 'SSO',
|
||||
lastName: 'userExist',
|
||||
email: 'anotherUser1@tooljet.io',
|
||||
groups: ['all_users'],
|
||||
organization: current_organization,
|
||||
});
|
||||
|
||||
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/common/git')
|
||||
.send({ token, organizationId: current_organization.id });
|
||||
|
||||
expect(response.statusCode).toBe(201);
|
||||
|
||||
expect(gitAuthResponse).toBeCalledWith('https://github.host.com/login/oauth/access_token', expect.anything());
|
||||
expect(gitGetUserResponse).toBeCalledWith('https://github.host.com/api/v3/user', expect.anything());
|
||||
expect(Object.keys(response.body).sort()).toEqual(authResponseKeys);
|
||||
|
||||
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');
|
||||
|
|
|
|||
|
|
@ -583,27 +583,164 @@ describe('oauth controller', () => {
|
|||
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',
|
||||
'org_environment_variable_create',
|
||||
'org_environment_variable_update',
|
||||
'org_environment_variable_delete',
|
||||
'folder_delete',
|
||||
'folder_update',
|
||||
].sort()
|
||||
);
|
||||
expect(Object.keys(group_permissions[0]).sort()).toEqual(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
await orgUser.reload();
|
||||
expect(orgUser.status).toEqual('active');
|
||||
});
|
||||
it('should return login info when the user exist and hostname exist in configs', async () => {
|
||||
await ssoConfigsRepository.update(sso_configs.id, {
|
||||
configs: { clientId: 'some-client-id', hostName: 'https://github.host.com' },
|
||||
});
|
||||
|
||||
const { orgUser } = await createUser(app, {
|
||||
firstName: 'SSO',
|
||||
lastName: 'userExist',
|
||||
email: 'anotherUser1@tooljet.io',
|
||||
groups: ['all_users'],
|
||||
organization: current_organization,
|
||||
});
|
||||
|
||||
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(gitAuthResponse).toBeCalledWith('https://github.host.com/login/oauth/access_token', expect.anything());
|
||||
expect(gitGetUserResponse).toBeCalledWith('https://github.host.com/api/v3/user', expect.anything());
|
||||
expect(Object.keys(response.body).sort()).toEqual(authResponseKeys);
|
||||
|
||||
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(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
await orgUser.reload();
|
||||
expect(orgUser.status).toEqual('active');
|
||||
});
|
||||
it('should return login info when the user does not exist and email id not available and sign up is enabled, host name configured', async () => {
|
||||
await ssoConfigsRepository.update(sso_configs.id, {
|
||||
configs: { clientId: 'some-client-id', hostName: 'https://github.host.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: '',
|
||||
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(gitAuthResponse).toBeCalledWith('https://github.host.com/login/oauth/access_token', expect.anything());
|
||||
expect(gitGetUserResponse).toBeCalledWith('https://github.host.com/api/v3/user', expect.anything());
|
||||
expect(gitGetUserEmailResponse).toBeCalledWith(
|
||||
'https://github.host.com/api/v3/user/emails',
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
expect(Object.keys(response.body).sort()).toEqual(authResponseKeys);
|
||||
|
||||
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(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -1122,27 +1259,164 @@ describe('oauth controller', () => {
|
|||
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',
|
||||
'org_environment_variable_create',
|
||||
'org_environment_variable_update',
|
||||
'org_environment_variable_delete',
|
||||
'folder_delete',
|
||||
'folder_update',
|
||||
].sort()
|
||||
);
|
||||
expect(Object.keys(group_permissions[0]).sort()).toEqual(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
await orgUser.reload();
|
||||
expect(orgUser.status).toEqual('active');
|
||||
});
|
||||
it('should return login info when the user exist and hostname exist in configs', async () => {
|
||||
await ssoConfigsRepository.update(sso_configs.id, {
|
||||
configs: { clientId: 'some-client-id', hostName: 'https://github.host.com' },
|
||||
});
|
||||
|
||||
const { orgUser } = await createUser(app, {
|
||||
firstName: 'SSO',
|
||||
lastName: 'userExist',
|
||||
email: 'anotherUser1@tooljet.io',
|
||||
groups: ['all_users'],
|
||||
organization: current_organization,
|
||||
});
|
||||
|
||||
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(gitAuthResponse).toBeCalledWith('https://github.host.com/login/oauth/access_token', expect.anything());
|
||||
expect(gitGetUserResponse).toBeCalledWith('https://github.host.com/api/v3/user', expect.anything());
|
||||
expect(Object.keys(response.body).sort()).toEqual(authResponseKeys);
|
||||
|
||||
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(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
await orgUser.reload();
|
||||
expect(orgUser.status).toEqual('active');
|
||||
});
|
||||
it('should return login info when the user does not exist and email id not available and sign up is enabled, host name configured', async () => {
|
||||
await ssoConfigsRepository.update(sso_configs.id, {
|
||||
configs: { clientId: 'some-client-id', hostName: 'https://github.host.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: '',
|
||||
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(gitAuthResponse).toBeCalledWith('https://github.host.com/login/oauth/access_token', expect.anything());
|
||||
expect(gitGetUserResponse).toBeCalledWith('https://github.host.com/api/v3/user', expect.anything());
|
||||
expect(gitGetUserEmailResponse).toBeCalledWith(
|
||||
'https://github.host.com/api/v3/user/emails',
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
expect(Object.keys(response.body).sort()).toEqual(authResponseKeys);
|
||||
|
||||
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(groupPermissionsKeys);
|
||||
expect(app_group_permissions).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue