Shrushti Polekar eebd3bb661
Feat(ui): SSO configuration from UI and Scim bot token generate revoke functionality and Group Mapping in settings page (#21839)
* added scim bot generate revoke token functionality on settings page

* update global setting constant

* minor code refactor

* WIP: SSO Configuration from UI

* Update generated TypeScript types

* Copilot suggestions addressed

* Test Endpoint added

* Added update security configuration test

* added sso configuration rjsf form

* minor  fixes

* Update generated TypeScript types

* update scim component

* Fix Merge Conflicts

* Remove extra comma

* update sso form for oidc client providers

* SAML configuration fixes

* Update generated TypeScript types

* Update generated TypeScript types

* add support for selective schema generation by file name

* fix acces token card issue and array fields ui issue

* Saml registration fix

* Scim configuration saved

* refactor code

* scim config issues fixed

* fix enableSelfSignup

* scim enabling from settings

* Test validation enpoint changes

* fix ldap issues

* minor refactor

* minor updates

* update settings call for scim

* update bot details in scim card

* minor style fixes

* Adding enhanced validators

* update confidential client configurations

* Auth0 validator

* update jwt for saml

* Saml validator changes

* Okta validator fix

* fix saml certificate formatting and select widgets

* remove client type from ui for ldap and saml

* Okta validation rectified

* Google validator improved

* update select component

* fix error messages

* added unit test

* Azure validator rectified

* Validation issues solved for auth0

* add oidc prefix for oidc client fields

* fix type issues

* style fixes for scim token card

* Update cognito validator

* refactor file names

* added e2e tests

* minor fixes

* added content for docs in md files

* implement  new design

* form style updates

* fix doc styles and provider selection styles

* fix provider selection style

* update local file

* group client fields together

* added provider name

* overview tab changes

* update form styles for configure tab

* update toggle styles

* update breadcrumb texts and provider name in text

* minor fix in localization

* minor fix for basic provider

* update breadcrumb styles and minor local file update

* minor fixes

* minor fix for local file

* fix styles for configured form

* minor fixes in styles

* fix redirect issue of my-data for non oidc sso

* fix build issue and refactor code

* update saml and ldap icons

* minor updates in icon

* typo fix

* breadcrumb and style fixes

* fix test

* update patch call

* minor fixes for access token card and code refactor

* refactor code to remove unused files

* added ldap and custom oidc doc content

* fix overview tab issue for scim and enable sso

* Patch issue fixed for authentication Configuration

* Implement unified authentication endpoints across all providers

* Memory leak issue solved

* Mcp md file

* apply spotless

* Added complete flow test for oidc

* refactor css files

* minor style updates

* cancel form functionality

* update placeholders

* update cancel modal

* minor update for saving existing config

* fix minor css issue

* integrate unified api

* remove clientid and callbackurl for confidential client type and added  jwtPrincipalClaimsMapping

* fix breadcrumb issue

* refactor files and folder structure

* minor fix

* refactor code and add disable fields styles and cancel btn functionality for existing sso

* added localization file changes

* Patch operation issue fixed

* Update generated TypeScript types

* update patch call

* patch call update for enable self signup

* remove enable selfsignup from then form since its present in the toggle

* added enable self signup field for non existing sso form

* minor code revert for enabling fields

* Update generated TypeScript types

* Redirect uri, password encoding fixes for basic and ldap

* refactor code and encode password and added /auth/callback in redirecturl

* minor  fixes

* added group mapping

* cancel modal save btn fix and logout fix

* minor fix for save btn functionality for cancel modal

* minor update in localization file

* address pr comments for ssoconfigform and css file names

* address pr comments for sso doc panel

* address pr comments around provider selector

* fix breadcrumb

* update localization file and remove unwanted files

* address pr comments related to basic auth provider

* extracted proxy code into separate func and added dev mode check

* remove unnecessary validate call happening during patch calls

* address pr comment related to tab

* update sso icon

* minor fix

* address parseSchema related pr comment

* address pr comment related to config fields constants

* added default value for callback url

* added default value for response type and clientAuthenticationMethod

* minor fix for callback url

* minor style fix

* Changed response to json for basic and ldap login

* revert unified api changes done for basic login

* made admin principal as required

* fix playwright for llogin test failure

* fix failing unit test

* fix login e2e test

* refresh call

* fix failing unit test

* fix unit test

* fix test

* remove setRefreshToken

* added default values for google

* minor style fixes

* minor text update

* Google credential validation, scope validation

* Discovery uri validation added with Auth0

* Discovery uri check added for okta

* minor style fixes

* minor checkbox fix

* minor required field fix

* minro fix

* AWS cognito validator

* google api depdendency added

* Update generated TypeScript types

* minor fixes

* minor fix for array fields cursor style issue

* Modified saml validator

* Admin principal respected while logging in

* Added tests for validators

* callback url update

* custom oidc validator

* added default values for saml

* custom oidc fix

* Saml validator issue solved

* Custom oidc publickeyurl validation

* validation for prompt

* test fix

* fix test

* TC fixed

* mvn spotless apply

* Addressed review comments

* Static method issue in Security COnfiguration manager fixed

---------

Co-authored-by: aji-aju <ajithprasad770@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Mohit Yadav <105265192+mohityadav766@users.noreply.github.com>
Co-authored-by: mohitdeuex <mohit.y@deuexsolutions.com>
Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
Co-authored-by: Ajith Prasad <37380177+aji-aju@users.noreply.github.com>
2025-09-23 13:23:46 +05:30

232 lines
6.7 KiB
JavaScript

/*
* Copyright 2024 Collate.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* eslint-disable */
const $RefParser = require('@apidevtools/json-schema-ref-parser');
const path = require('path');
const fs = require('fs');
const fse = require('fs-extra');
const process = require('process');
const cwd = process.cwd();
const schemaDir =
'../../../../../openmetadata-spec/src/main/resources/json/schema';
const globalParserOptions = {
continueOnError: true,
dereference: {
circular: true,
},
};
const parser = new $RefParser(globalParserOptions);
// Function to recursively remove any object by key
function removeObjectByKey(obj, keyToRemove) {
if (typeof obj == 'object') {
for (const prop in obj) {
if (prop === keyToRemove) {
// If the property key matches the key to remove, delete it
delete obj[prop];
} else {
// Recursively call the function on the property's value
obj[prop] = removeObjectByKey(obj[prop], keyToRemove);
}
}
}
return obj;
}
async function parseSchema(filePath, destPath, shouldDereference = false) {
try {
const fileDir = `${cwd}/${path.dirname(filePath)}`;
const fileName = path.basename(filePath);
process.chdir(fileDir);
let parsedSchema = await parser.parse(fileName);
if (shouldDereference || fileName.startsWith('dbt')) {
parsedSchema = await parser.dereference(parsedSchema);
}
const api = await parser.bundle(parsedSchema);
const dirname = `${cwd}/${path.dirname(destPath)}`;
const updatedAPIWithoutID = removeObjectByKey(api, '$id');
if (!fs.existsSync(dirname)) {
try {
fs.mkdirSync(dirname, { recursive: true });
} catch (err) {
console.log(err);
}
}
fs.writeFileSync(
`${cwd}/${destPath}`,
JSON.stringify(updatedAPIWithoutID, null, 2)
);
} catch (err) {
console.log(err);
} finally {
process.chdir(cwd);
}
}
// Function to traverse directories and parse files
async function traverseDirectory(
Directory,
playDir,
destDir,
shouldDereference = false
) {
const Files = fs.readdirSync(Directory);
for (const File of Files) {
const Absolute = path.join(Directory, File);
if (fs.statSync(Absolute).isDirectory()) {
await traverseDirectory(Absolute, playDir, destDir, shouldDereference);
} else {
const name = Absolute.replace(playDir, destDir);
await parseSchema(Absolute, name, shouldDereference);
}
}
}
// Function to copy source files
function copySourceFiles(rootDir) {
try {
fse.copySync(schemaDir, `${rootDir}/schema`);
} catch (err) {
console.error(err);
}
}
// Main function to handle schema parsing
async function main(rootDir, srcDir, destDir, shouldDereference = false) {
const playDir = `${rootDir}/${srcDir}`;
try {
if (fs.existsSync(destDir)) {
fs.rmSync(destDir, { recursive: true });
}
fs.mkdirSync(destDir, { recursive: true });
copySourceFiles(rootDir);
await traverseDirectory(playDir, playDir, destDir, shouldDereference);
} catch (err) {
console.log(err);
} finally {
// Cleanup: Remove the temporary directory
if (fs.existsSync(rootDir)) {
fs.rmSync(rootDir, { recursive: true, force: true });
}
}
}
// Function to parse Application schemas
async function parseApplicationSchemas() {
const appSchemaDir = 'src/utils/ApplicationSchemas';
const destDir = 'src/jsons/applicationSchemas';
try {
// Create destination directory if it doesn't exist
if (!fs.existsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true });
} else {
// Clean existing destination directory
fs.rmSync(destDir, { recursive: true });
fs.mkdirSync(destDir, { recursive: true });
}
// Get all JSON files in ApplicationSchemas directory
const files = fs.readdirSync(appSchemaDir).filter(file => file.endsWith('.json'));
for (const file of files) {
const filePath = path.join(appSchemaDir, file);
const destPath = path.join(destDir, file);
try {
// Change to the source directory for relative path resolution
const fileDir = path.dirname(filePath);
const originalCwd = process.cwd();
process.chdir(fileDir);
// Parse and dereference the schema
let parsedSchema = await parser.parse(file);
parsedSchema = await parser.dereference(parsedSchema);
// Remove $id fields
const updatedSchema = removeObjectByKey(parsedSchema, '$id');
// Change back to original directory
process.chdir(originalCwd);
// Write the processed schema to destination
fs.writeFileSync(destPath, JSON.stringify(updatedSchema, null, 2));
console.log(`Processed ApplicationSchema: ${file}`);
} catch (err) {
console.error(`Error processing ${file}:`, err.message);
process.chdir(cwd);
}
}
} catch (err) {
console.error('Error parsing Application schemas:', err);
}
}
// Execute the parsing for connection and ingestion schemas
async function runParsers() {
// For connection schemas
await main(
'connTemp',
'schema/entity/services/connections',
'src/jsons/connectionSchemas/connections',
true
);
// For ingestion schemas (with dereferencing for dbt schemas)
await main(
'ingestionTemp',
'schema/metadataIngestion',
'src/jsons/ingestionSchemas'
);
await main(
'workflowTemp',
'schema/governance/workflows/elements/nodes',
'src/jsons/governanceSchemas'
);
// Parse Application schemas
await parseApplicationSchemas();
// Parse configuration schemas directly
const configDir = 'src/jsons/configuration';
if (!fs.existsSync(configDir)) {
fs.mkdirSync(configDir, { recursive: true });
}
const configSchemas = [
'authenticationConfiguration.json',
'authorizerConfiguration.json',
];
for (const configFile of configSchemas) {
const srcPath = `${schemaDir}/configuration/${configFile}`;
const destPath = `${configDir}/${configFile}`;
// Only authenticationConfiguration.json needs dereferencing (has external $ref)
const needsDereference = configFile === 'authenticationConfiguration.json';
await parseSchema(srcPath, destPath, needsDereference);
}
}
runParsers();