Skip to content

Commit

Permalink
⭐ New Search Attribute Config #64
Browse files Browse the repository at this point in the history
  • Loading branch information
yannick-beot-sp committed Mar 2, 2024
1 parent 2652bfb commit b16d4a1
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 6 deletions.
26 changes: 20 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,11 @@
"light": "resources/light/import.svg",
"dark": "resources/dark/import.svg"
}
},
{
"command": "vscode-sailpoint-identitynow.new-attribute-search.view",
"title": "New Search Attribute",
"icon": "$(add)"
}
],
"menus": {
Expand Down Expand Up @@ -734,6 +739,10 @@
{
"command": "vscode-sailpoint-identitynow.forms.import.icon-view",
"when": "never"
},
{
"command": "vscode-sailpoint-identitynow.new-attribute-search.view",
"when": "never"
}
],
"view/title": [
Expand Down Expand Up @@ -982,11 +991,11 @@
},
{
"command": "vscode-sailpoint-identitynow.new-role.view",
"when": "view == vscode-sailpoint-identitynow.view && viewItem =~ /^roles/"
"when": "view == vscode-sailpoint-identitynow.view && viewItem == roles"
},
{
"command": "vscode-sailpoint-identitynow.new-role.view-icon",
"when": "view == vscode-sailpoint-identitynow.view && viewItem =~ /^roles/",
"when": "view == vscode-sailpoint-identitynow.view && viewItem == roles",
"group": "inline@1"
},
{
Expand All @@ -1009,20 +1018,20 @@
},
{
"command": "vscode-sailpoint-identitynow.csv.export.roles.view",
"when": "view == vscode-sailpoint-identitynow.view && viewItem =~ /^roles/"
"when": "view == vscode-sailpoint-identitynow.view && viewItem == roles"
},
{
"command": "vscode-sailpoint-identitynow.csv.export.roles-icon.view",
"when": "view == vscode-sailpoint-identitynow.view && viewItem =~ /^roles/",
"when": "view == vscode-sailpoint-identitynow.view && viewItem == roles",
"group": "inline@3"
},
{
"command": "vscode-sailpoint-identitynow.csv.import.roles.view",
"when": "view == vscode-sailpoint-identitynow.view && viewItem =~ /^roles/"
"when": "view == vscode-sailpoint-identitynow.view && viewItem == roles"
},
{
"command": "vscode-sailpoint-identitynow.csv.import.roles-icon.view",
"when": "view == vscode-sailpoint-identitynow.view && viewItem =~ /^roles/",
"when": "view == vscode-sailpoint-identitynow.view && viewItem == roles",
"group": "inline@2"
},
{
Expand All @@ -1046,6 +1055,11 @@
"command": "vscode-sailpoint-identitynow.forms.import.icon-view",
"when": "view == vscode-sailpoint-identitynow.view && viewItem == form-definitions",
"group": "inline@2"
},
{
"command": "vscode-sailpoint-identitynow.new-attribute-search.view",
"when": "view == vscode-sailpoint-identitynow.view && viewItem == search-attributes",
"group": "inline@2"
}
],
"editor/context": [
Expand Down
92 changes: 92 additions & 0 deletions src/commands/NewAttributeSearchConfigCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as vscode from 'vscode';
import { TenantService } from "../services/TenantService";
import { SearchAttributesTreeItem } from '../models/IdentityNowTreeItem';
import { IdentityNowClient } from '../services/IdentityNowClient';
import { getResourceUri } from '../utils/UriUtils';
import { SearchAttributeConfigBeta } from 'sailpoint-api-client';
import { runWizard } from '../wizard/wizard';
import { InputPromptStep } from '../wizard/inputPromptStep';
import { Validator } from '../validator/validator';
import { WizardContext } from '../wizard/wizardContext';
import { QuickPickTenantStep } from '../wizard/quickPickTenantStep';
import { openPreview } from '../utils/vsCodeHelpers';
import { QuickPickSourceStep } from '../wizard/quickPickSourceStep';
import { QuickPickAccountSchemaStep } from '../wizard/quickPickAccountSchemaStep';
import * as commands from "../commands/constants";

const searchAttributeNameValidator = new Validator({
required: true,
maxLength: 128,
regexp: '^[A-Za-z0-9 _:;,={}@()#-|^%$!?.*]+$'
});

/**
* Command used to create a Search Attribute
*/
export class NewAttributeSearchConfigCommand {

constructor(private readonly tenantService: TenantService) { }

async execute(node?: SearchAttributesTreeItem): Promise<void> {

console.log("> NewAttributeSearchConfigCommand.newRole", node);
const context: WizardContext = {};

// if the command is called from the Tree View
if (node !== undefined && node instanceof SearchAttributesTreeItem) {
context["tenant"] = await this.tenantService.getTenant(node.tenantId);
}

let client: IdentityNowClient | undefined = undefined;
const values = await runWizard({
title: "Creation of a search attribute",
hideStepCount: false,
promptSteps: [
new QuickPickTenantStep(
this.tenantService,
async (wizardContext) => {
client = new IdentityNowClient(
wizardContext["tenant"].id, wizardContext["tenant"].tenantName);
}),
new InputPromptStep({
name: "searchAttribute",
displayName: "search attribute",
options: {
validateInput: (s: string) => { return searchAttributeNameValidator.validate(s); }
}
}),
new QuickPickSourceStep(() => { return client!; }),
new QuickPickAccountSchemaStep(() => { return client!; }),
]
}, context);
console.log({ values });
if (values === undefined) { return; }

const name = values["searchAttribute"].trim()
const searchAttribute: SearchAttributeConfigBeta = {
name: name,
displayName: name,
applicationAttributes: {}
}
searchAttribute.applicationAttributes[values["source"].id] = values["attribute"].name

await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: 'Creating Attribute Search...',
cancellable: false
}, async (task, token) => {

await client.createSearchAttribute(searchAttribute)
const newUri = getResourceUri(
values["tenant"].tenantName,
"accounts/search-attribute-config",
name,
name,
true
)

openPreview(newUri);
vscode.commands.executeCommand(commands.REFRESH_FORCED);
});
}
}
2 changes: 2 additions & 0 deletions src/commands/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,5 @@ export const IMPORT_FORMS_ICON_VIEW = 'vscode-sailpoint-identitynow.forms.import

export const EDIT_PUBLIC_IDENTITIES_CONFIG = 'vscode-sailpoint-identitynow.tenant.edit.public-identities-config';
export const EDIT_ACCESS_REQUEST_CONFIG = 'vscode-sailpoint-identitynow.tenant.edit.access-request-config';

export const NEW_SEARCH_ATTRIBUTE = 'vscode-sailpoint-identitynow.new-attribute-search.view'
7 changes: 7 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { WorkflowExportCommand } from './commands/workflow/WorkflowExportCommand
import { WorkflowImporterTreeViewCommand } from './commands/workflow/WorkflowImporterTreeViewCommand';
import { EditPublicIdentitiesConfigCommand } from './commands/editPublicIdentitiesConfigCommand';
import { EditAccessRequestConfigCommand } from './commands/editAccessRequestConfigCommand';
import { NewAttributeSearchConfigCommand } from './commands/NewAttributeSearchConfigCommand';

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
Expand Down Expand Up @@ -423,6 +424,12 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand(commands.IMPORT_FORMS_ICON_VIEW,
formDefinitionImporterTreeViewCommand.execute, formDefinitionImporterTreeViewCommand));

// Attribute Search Config
const newAttributeSearchConfigCommand = new NewAttributeSearchConfigCommand(tenantService)
context.subscriptions.push(
vscode.commands.registerCommand(commands.NEW_SEARCH_ATTRIBUTE,
newAttributeSearchConfigCommand.execute, newAttributeSearchConfigCommand));
}

// this method is called when your extension is deactivated
Expand Down
8 changes: 8 additions & 0 deletions src/services/IdentityNowClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1463,6 +1463,14 @@ export class IdentityNowClient {
const result = await api.getSearchAttributeConfig()
return result.data;
}

public async createSearchAttribute(searchAttributeConfigBeta: SearchAttributeConfigBeta): Promise<void> {
console.log("> createSearchAttribute");
const apiConfig = await this.getApiConfiguration();
const api = new SearchAttributeConfigurationBetaApi(apiConfig);
await api.createSearchAttributeConfig({searchAttributeConfigBeta})
}

/////////////////////////
//#endregion Search attributes
/////////////////////////
Expand Down
32 changes: 32 additions & 0 deletions src/wizard/quickPickAccountSchemaStep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

import * as vscode from 'vscode';
import { QuickPickPromptStep } from "./quickPickPromptStep";
import { WizardContext } from "./wizardContext";
import { IdentityNowClient } from "../services/IdentityNowClient";

export class QuickPickAccountSchemaStep extends QuickPickPromptStep<WizardContext, vscode.QuickPickItem> {
constructor(
getIdentityNowClient: () => IdentityNowClient,
) {
super({
name: "attribute",
options: {
matchOnDescription: true,
matchOnDetail: true
},
skipIfOne: true,
items: async (context: WizardContext): Promise<vscode.QuickPickItem[]> => {
const client = getIdentityNowClient();
const source = context["source"];
const results = (await client.getSchemas(source.id))
.find(x => x.name === "account")?.attributes?.map(x => ({
...x,
label: x.name,
description: x.description
}));
return results;
}
})
}
}

0 comments on commit b16d4a1

Please sign in to comment.