Skip to content

Commit

Permalink
Renumbering issues
Browse files Browse the repository at this point in the history
  • Loading branch information
yoelhor committed Mar 16, 2021
1 parent e73bca5 commit 7b59d83
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 87 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## March 2021

- User journey and sub journey renumbering ([#41](https://github.com/azure-ad-b2c/vscode-extension/pull/41/)).

## February 2021

- Added the ability for xml files to be in nested folders.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ You can add following elements to your policy. Make sure your cursor is located

![Adding XML elements](media/commands.png)

## Orchestration steps renumbering

The **B2C Renumber policy** (`Shift+Ctrl+r`) command renumbers all of the user journeys and sub journeys orchestration steps.

![Orchestration steps renumbering](media/renumbering.gif)

## Smart Copy & Paste

When you customize an XML element in the extension policy, **Smart Copy** allows you to copy the entire element with its parent's elements from the base policy. For example, when you copy the AAD-UserWriteUsingAlternativeSecurityId technical profile, Smart Copy generates an XML snippet containing the following elements so you don't need to search for the parent's element, such as the claim provider.
Expand Down
Binary file added media/renumbering.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added media/renumbering.mp4
Binary file not shown.
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@
"mac": "shift+cmd+v",
"when": "editorTextFocus"
},
{
"command": "extension.policy.renumber",
"key": "shift+ctrl+r",
"mac": "shift+cmd+r",
"when": "editorTextFocus"
},
{
"command": "extension.policy.upload",
"key": "shift+ctrl+u",
Expand Down Expand Up @@ -284,4 +290,4 @@
"xpath": "0.0.27",
"yo": "^3.1.0"
}
}
}
177 changes: 95 additions & 82 deletions src/PolicyCommands.ts → src/OrchestrationStepsRenumber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,96 @@ import { PolicyFile } from './PolicyBuild';

const _selector = require('xpath').useNamespaces({ "ns": "http://schemas.microsoft.com/online/cpim/schemas/2013/06" });

export default class OrchestrationStepsRenumber {

// Renumber a single policy document (using the editor)
static RenumberPolicyDocument(): any {
try {
var editor: vscode.TextEditor = vscode.window.activeTextEditor as vscode.TextEditor;

if (!editor) {
vscode.window.showErrorMessage("No document is open");
return;
}

var xmlDoc = new DOMParser().parseFromString(editor.document.getText(), "application/xml");

editor.edit((editBuilder) => {
OrchestrationStepsRenumber.renumberOrchestrationSteps(xmlDoc, editBuilder, "/ns:TrustFrameworkPolicy/ns:UserJourneys/ns:UserJourney");
OrchestrationStepsRenumber.renumberOrchestrationSteps(xmlDoc, editBuilder, "/ns:TrustFrameworkPolicy/ns:SubJourneys/ns:SubJourney");
});

} catch (e) {
vscode.window.showErrorMessage(e.message);
}
}

// Renumber multiple policies (using the file system)
static RenumberPolicies(files): any {
let policies: Map<string, Policy> = new Map();
for (let file of files) {
let policy = new Policy(file);
if (!policy.policyId) {
continue;
}
policies.set(policy.policyId, policy);
}

// Iterate over all the policies to determine if they have a base file
for (let policy of policies.values()) {
let base = policy.selector("string(/ns:TrustFrameworkPolicy/ns:BasePolicy/ns:PolicyId)");
if (base && policies.has(base)) {
policy.base = policies.get(base);
}
}

for (let policy of policies.values()) {
policy.process();
}
}

// Renumber documents' user journeys, or sub journeys
private static renumberOrchestrationSteps(xmlDoc, editBuilder, parentElement): any {
let journeys = _selector(parentElement, xmlDoc);
if (journeys.length === 0) {
vscode.window.showInformationMessage("No journeys to renumber");
}

for (let journey of journeys) {
let steps = _selector("./ns:OrchestrationSteps/ns:OrchestrationStep", journey);
if (steps.length === 0) {
vscode.window.showInformationMessage("No steps to renumber");
continue;
}

for (let i = 0; i < steps.length; i++) {
let orderAttr;
for (let j = 0; j < steps[i].attributes.length; j++) {
if (steps[i].attributes[j].name === "Order") {
orderAttr = steps[i].attributes[j];
break;
}
}
if (!orderAttr) {
vscode.window.showWarningMessage(`Step ${i} missing order attribute. Will not be renumbered!`);
continue;
}

let start = new vscode.Position(orderAttr.lineNumber - 1, orderAttr.columnNumber);
let end = new vscode.Position(orderAttr.lineNumber - 1, orderAttr.columnNumber + orderAttr.nodeValue.length);

let range = new vscode.Range(start, end);

editBuilder.replace(range, (i + 1).toString());
}
}


vscode.window.showInformationMessage("Steps renumbered successfully");
}

}

class Policy {
xml: Document;
file: PolicyFile;
Expand Down Expand Up @@ -48,7 +138,7 @@ class Policy {
if (this.base && this.base.journeys.has(journeyId)) {
vscode.window.showInformationMessage(`Skipped renumbering ${this.policyId} because it has a base journey in another file`);
continue; // We won't renumber anything which has the journey defined in its base because
// it's impossible to know what the programmer intends
// it's impossible to know what the programmer intends
}
let steps = _selector("./ns:OrchestrationSteps/ns:OrchestrationStep", journey);
for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
Expand All @@ -58,8 +148,8 @@ class Policy {
continue;
}
let orderAttr = orderAttrs[0];
if (orderAttr.value !== (stepIndex+1).toString()) {
orderAttr.value = (stepIndex+1).toString();
if (orderAttr.value !== (stepIndex + 1).toString()) {
orderAttr.value = (stepIndex + 1).toString();
this.setOrder(orderAttr);
this.renumbered++;
}
Expand All @@ -85,87 +175,10 @@ class Policy {
this.file.Data = this.file.Data.trimRight();
if (this.file.SubFolder) {
fs.writeFile(path.join(vscode.workspace.workspaceFolders[0].uri.fsPath, this.file.SubFolder, this.file.FileName),
this.file.Data, e => vscode.window.showErrorMessage(e.message));
this.file.Data, e => vscode.window.showErrorMessage(e.message));
} else {
fs.writeFile(path.join(vscode.workspace.workspaceFolders[0].uri.fsPath, this.file.FileName),
this.file.Data, e => vscode.window.showErrorMessage(e.message));
this.file.Data, e => vscode.window.showErrorMessage(e.message));
}
}
}

export default class PolicyCommands {
static renumberPolicies(files): any {
let policies: Map<string, Policy> = new Map();
for (let file of files) {
let policy = new Policy(file);
if (!policy.policyId) {
continue;
}
policies.set(policy.policyId, policy);
}

// Iterate over all the policies to determine if they have a base file
for (let policy of policies.values()) {
let base = policy.selector("string(/ns:TrustFrameworkPolicy/ns:BasePolicy/ns:PolicyId)");
if (base && policies.has(base)) {
policy.base = policies.get(base);
}
}

for (let policy of policies.values()) {
policy.process();
}
}

static renumberPolicyCommand(): any {
try {
var editor: vscode.TextEditor = vscode.window.activeTextEditor as vscode.TextEditor;

if (!editor) {
vscode.window.showErrorMessage("No document is open");
return;
}

var xmlDoc = new DOMParser().parseFromString(editor.document.getText(), "application/xml");

let journeys = _selector("/ns:TrustFrameworkPolicy/ns:UserJourneys/ns:UserJourney", xmlDoc);
if (journeys.length === 0) {
vscode.window.showInformationMessage("No journeys to renumber");
}

for (let journey of journeys) {
let steps = _selector("./ns:OrchestrationSteps/ns:OrchestrationStep", journey);
if (steps.length === 0) {
vscode.window.showInformationMessage("No steps to renumber");
continue;
}
editor.edit((editBuilder) => {
for (let i = 0; i < steps.length; i++) {
let orderAttr;
for (let j = 0; j < steps[i].attributes.length; j++) {
if (steps[i].attributes[j].name === "Order") {
orderAttr = steps[i].attributes[j];
break;
}
}
if (!orderAttr) {
vscode.window.showWarningMessage(`Step ${i} missing order attribute. Will not be renumbered!`);
continue;
}

let start = new vscode.Position(orderAttr.lineNumber - 1, orderAttr.columnNumber);
let end = new vscode.Position(orderAttr.lineNumber - 1, orderAttr.columnNumber + orderAttr.nodeValue.length);

let range = new vscode.Range(start, end);

editBuilder.replace(range, (i + 1).toString());
}
});
}
vscode.window.showInformationMessage("Steps renumbered successfully");
} catch (e) {
vscode.window.showErrorMessage(e.message);
}
}

}
4 changes: 2 additions & 2 deletions src/PolicyBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vscode from 'vscode';
import fs = require('fs');
import path = require('path');
import Consts from './Consts';
import PolicyCommands from './PolicyCommands';
import OrchestrationStepsRenumber from './OrchestrationStepsRenumber';

export default class PolicBuild {
static Build() {
Expand Down Expand Up @@ -67,7 +67,7 @@ export default class PolicBuild {
// Automatically renumber orchestration steps if they are out of order
let config = vscode.workspace.getConfiguration('aadb2c');
if (config.autoRenumber) {
PolicyCommands.renumberPolicies(policyFiles);
OrchestrationStepsRenumber.RenumberPolicies(policyFiles);
}

// Get the app settings
Expand Down
4 changes: 2 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import CompletionProvider from './CompletionProvider';
import XsdHelper from './services/XsdHelper';
import PolicyUpload from './PolicyUpload';
import B2CArtifacts from './B2CArtifacts';
import PolicyCommands from './PolicyCommands';
import OrchestrationStepsRenumber from './OrchestrationStepsRenumber';

// 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 @@ -102,7 +102,7 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('extension.policy.upload', () => PolicyUpload.uploadCurrentPolicy()));

// Upload currently open Policy
context.subscriptions.push(vscode.commands.registerCommand('extension.policy.renumber', () => PolicyCommands.renumberPolicyCommand()));
context.subscriptions.push(vscode.commands.registerCommand('extension.policy.renumber', () => OrchestrationStepsRenumber.RenumberPolicyDocument()));

// Upload all policies for the default environment
context.subscriptions.push(vscode.commands.registerCommand('extension.policy.uploadAll', () => PolicyUpload.uploadAllPolicies()));
Expand Down

0 comments on commit 7b59d83

Please sign in to comment.